bmad-code-org/BMAD-METHOD · error · Error

External module ' ' not found in the BMad registry

Error message

External module '${moduleCode}' not found in the BMad registry

What it means

Thrown by ExternalModuleManager.cloneExternalModule() when getModuleByCode() returns null — the provided moduleCode is not found in the bundled bmad-modules.yaml registry, neither as a current code nor as a registered alias. Every external module must be declared in the registry before it can be cloned.

Solutions

  1. Run the installer's module listing command to see available module codes.
  2. Check bmad-modules.yaml for the correct module code.
  3. If the module was renamed, find the new code and update your configuration.
  4. If installing a custom module not in the registry, use the custom module URL install path instead.

Example fix

// before
await extMgr.cloneExternalModule('old-module-name');

// after
await extMgr.cloneExternalModule('new-module-name');
// verify with:
// const mods = await extMgr.listAvailable();
// console.log(mods.map(m => m.code));
Defensive patterns

Strategy: validation

Validate before calling

// Verify module exists in registry before cloning
const moduleInfo = await extMgr.getModuleByCode(moduleCode);
if (!moduleInfo) {
  const available = await extMgr.listAvailable();
  const codes = available.map(m => m.code);
  throw new Error(`Module '${moduleCode}' not found. Available: ${codes.join(', ')}`);
}
await extMgr.cloneExternalModule(moduleCode, options);

Try / catch

try {
  await extMgr.cloneExternalModule(moduleCode, options);
} catch (e) {
  if (e.message.includes('not found in the BMad registry')) {
    const mods = await extMgr.listAvailable();
    console.error('Available modules:', mods.map(m => m.code).join(', '));
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling cloneExternalModule('unknown-code') or cloneExternalModule('old-name') where 'old-name' was removed and not listed in any module's aliases array. The lookup checks m.code === code and m.aliases.includes(code).

Common situations: A module was renamed and the old code wasn't added to the aliases list; the user typed the wrong module code; the registry YAML is outdated or missing the module entry; the module was deprecated and removed entirely.

Related errors


AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13). Data as JSON: /api/errors/084e37132a7e1faa. Report an issue: GitHub.

Appendix: source

Thrown at tools/installer/modules/external-manager.js:215

  }

  /**
   * Clone an external module repository to cache, resolving the requested
   * channel (stable / next / pinned) to a concrete git ref.
   *
   * @param {string} moduleCode - Code of the external module
   * @param {Object} options - Clone options
   * @param {boolean} [options.silent] - Suppress spinner output
   * @param {Object} [options.channelOptions] - Parsed channel flags. See
   *   modules/channel-plan.js. When absent, the module installs on its
   *   registry-declared default channel (typically 'stable').
   * @returns {string} Path to the cloned repository
   */
  async cloneExternalModule(moduleCode, options = {}) {
    const moduleInfo = await this.getModuleByCode(moduleCode);

    if (!moduleInfo) {
      throw new Error(`External module '${moduleCode}' not found in the BMad registry`);
    }

    // Normalize to the canonical code so cache dir, in-memory resolutions,
    // and log/error text stay consistent even when called with a renamed
    // module's prior alias (getModuleByCode resolves aliases above).
    moduleCode = moduleInfo.code;

    const cacheDir = this.getExternalCacheDir();
    const moduleCacheDir = path.join(cacheDir, moduleCode);
    const silent = options.silent || false;

    // Create cache directory if it doesn't exist
    await fs.ensureDir(cacheDir);

    // Helper to create a spinner or a no-op when silent
    const createSpinner = async () => {
      if (silent) {
        return {

View on GitHub (pinned to b70486b9bd)