Skip to content

fix(installer): descriptive error when module definition missing after clone#2377

Merged
bmadcode merged 3 commits into
mainfrom
fix/external-module-definition-error
May 13, 2026
Merged

fix(installer): descriptive error when module definition missing after clone#2377
bmadcode merged 3 commits into
mainfrom
fix/external-module-definition-error

Conversation

@bmadcode
Copy link
Copy Markdown
Collaborator

What

findExternalModuleSource now throws a clear, actionable error when a cloned module's repo doesn't contain the expected module definition path, instead of silently returning that non-existent path.

Why

When a stable tag predates a module restructure, the installer cloned the tagged version, couldn't find module_definition (e.g. skills/module.yaml) anywhere in the repo, then silently returned the configured (but non-existent) path as sourcePath. This caused a confusing ENOENT buried inside getFileList/copyModuleWithFiltering:

ENOENT: no such file or directory, scandir '~/.bmad/cache/external-modules/baut/skills'
    at async OfficialModules.getFileList (official-modules.js:785:21)
    at async OfficialModules.copyModuleWithFiltering (official-modules.js:519:25)
    at async OfficialModules.install (official-modules.js:303:5)

Users had no idea which module failed or why. Reported in #2372.

How

Replaced the silent return path.dirname(configuredPath) fallback with a thrown error that:

  • Names the module code and missing definition path
  • Includes the version/tag that was cloned
  • When the channel was stable, appends a --next=<code> hint so the user can recover immediately

Example new error

Error: Module 'baut' was downloaded but its module definition was not found.
Expected 'skills/module.yaml' to exist in version v1.14.0, but it is missing.
The repository may have been restructured after this release was tagged.
Try reinstalling with `--next=baut` to use the latest main branch instead.

Related

…g after clone

When a stable tag predates a module restructure (e.g. baut v1.14.0 had
payload/source dirs, but the registry pointed to skills/module.yaml which
only exists on main), findExternalModuleSource silently returned the
configured but non-existent path. This caused a confusing ENOENT inside
getFileList/copyModuleWithFiltering rather than a clear error.

Now throws with the version that was cloned and a --next hint when the
install channel was stable, so users know exactly how to recover.

Closes #2372
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 13, 2026

🤖 Augment PR Summary

Summary: Improves the installer’s external module source detection by throwing a clear error when the cloned repo/ref doesn’t contain the expected module definition file, instead of returning a non-existent path.
Why: Prevents confusing downstream ENOENT failures and provides actionable guidance (including a --next=<module> recovery hint for stable installs) when older tags predate repo restructures.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. No suggestions at this time.

Comment augment review to trigger a new review at any time.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

The PR improves error handling in external module installation by converting a silent fallback return into a descriptive error. When a cloned external module repository lacks the expected module structure, findExternalModuleSource now throws an error that includes the missing definition path, the recorded installed version, and a conditional hint to reinstall with --next if applicable.

Changes

External Module Source Discovery Error Messaging

Layer / File(s) Summary
Enhanced Missing Module Definition Error
tools/installer/modules/external-manager.js
When the cloned repository does not contain the configured module definition path, findExternalModuleSource now throws a descriptive error with the expected definition path, version context from ExternalModuleManager._resolutions, and a conditional --next reinstall hint for modules installed from the stable channel.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • bmad-code-org/BMAD-METHOD#2345: Both PRs modify tools/installer/modules/external-manager.js around external-module discovery—specifically findExternalModuleSource and module-structure handling.
  • bmad-code-org/BMAD-METHOD#2149: Both PRs modify findExternalModuleSource() to handle cases where the expected moduleDefinitionPath or module.yaml structure isn't found by changing resolution and error handling behavior.
  • bmad-code-org/BMAD-METHOD#2295: Both PRs adjust how external modules' expected module.yaml and module definition paths are found and handled during installation.

Suggested reviewers

  • pbean
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: replacing a silent fallback with a descriptive error when module definition is missing after clone.
Description check ✅ Passed The description is well-detailed and clearly related to the changeset, explaining what changed, why it was needed, and how it works.
Linked Issues check ✅ Passed The PR successfully addresses issue #2372 by throwing a clear error with module name, missing path, version, and recovery hint instead of silently returning non-existent paths.
Out of Scope Changes check ✅ Passed The change to external-manager.js is directly scoped to the linked issue, replacing a silent fallback with error handling for missing module definitions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/external-module-definition-error

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tools/installer/modules/external-manager.js (1)

1-1: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix Prettier formatting to unblock CI.

The pipeline reports code style issues that need to be resolved before merge.

Run the following command to fix:

prettier --write tools/installer/modules/external-manager.js

As per coding guidelines, tools/** should maintain proper code quality standards including formatting.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/installer/modules/external-manager.js` at line 1, Run Prettier on
tools/installer/modules/external-manager.js to fix formatting so CI passes:
execute the suggested formatter (prettier --write
tools/installer/modules/external-manager.js) or apply your editor’s Prettier
fix, save the file, and commit the updated formatting; ensure the change touches
the existing module import (const fs = require('../fs-native');) and nothing
else functionally changes before pushing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@tools/installer/modules/external-manager.js`:
- Line 1: Run Prettier on tools/installer/modules/external-manager.js to fix
formatting so CI passes: execute the suggested formatter (prettier --write
tools/installer/modules/external-manager.js) or apply your editor’s Prettier
fix, save the file, and commit the updated formatting; ensure the change touches
the existing module import (const fs = require('../fs-native');) and nothing
else functionally changes before pushing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f1a9c4fa-40e9-4100-b093-308c6474efea

📥 Commits

Reviewing files that changed from the base of the PR and between c48b6f3 and 5d282f9.

📒 Files selected for processing (1)
  • tools/installer/modules/external-manager.js

@bmadcode bmadcode merged commit 724867d into main May 13, 2026
5 checks passed
@bmadcode bmadcode deleted the fix/external-module-definition-error branch May 13, 2026 04:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Installation failed: ENOENT: no such file or directory

1 participant