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

marketplace.json contains no plugins

Error message

marketplace.json contains no plugins

What it means

Thrown by CustomModuleManager.discoverModules() when marketplace.json's plugins field is missing, not an array, or an empty array. The discovery flow expects at least one plugin entry to normalize and present to the user for selection.

Source

Thrown at tools/installer/modules/custom-module-manager.js:315

      return JSON.parse(await fs.readFile(marketplacePath, 'utf8'));
    } catch {
      return null;
    }
  }

  // ─── Discovery ────────────────────────────────────────────────────────────

  /**
   * Discover modules from pre-read marketplace.json data.
   * @param {Object} marketplaceData - Parsed marketplace.json content
   * @param {string|null} sourceUrl - Source URL for tracking (null for local paths)
   * @returns {Array<Object>} Normalized plugin list
   */
  async discoverModules(marketplaceData, sourceUrl) {
    const plugins = marketplaceData?.plugins;

    if (!Array.isArray(plugins) || plugins.length === 0) {
      throw new Error('marketplace.json contains no plugins');
    }

    return plugins.map((plugin) => this._normalizeCustomModule(plugin, sourceUrl, marketplaceData));
  }

  // ─── Source Resolution ────────────────────────────────────────────────────

  /**
   * High-level coordinator: parse input, clone if URL, determine discovery vs direct mode.
   * @param {string} input - URL or local path
   * @param {Object} [options] - Options passed to cloneRepo
   * @returns {Object} { parsed, rootDir, repoPath, sourceUrl, marketplace, mode: 'discovery'|'direct' }
   */
  async resolveSource(input, options = {}) {
    const parsed = this.parseSource(input);
    if (!parsed.isValid) throw new Error(parsed.error);

    let rootDir;

View on GitHub (pinned to b70486b9bd)

Solutions

  1. Open the source repository's .claude-plugin/marketplace.json and add a non-empty 'plugins' array with at least one plugin object.
  2. Verify the JSON structure matches the expected schema: { "plugins": [ { "name": "...", "skills": [...] } ] }.
  3. If the repo genuinely has no plugins, use the 'direct' install mode instead (remove the marketplace.json so the installer falls back).

Example fix

// before — .claude-plugin/marketplace.json
{ "plugins": [] }

// after
{
  "plugins": [
    {
      "name": "my-module",
      "description": "My custom module",
      "skills": ["./skills/my-skill"]
    }
  ]
}
Defensive patterns

Strategy: validation

Validate before calling

function hasValidPlugins(data) {
  return data && Array.isArray(data.plugins) && data.plugins.length > 0 &&
    data.plugins.every(p => p && typeof p.name === 'string');
}

const marketplace = await mgr.readMarketplaceJsonFromDisk(dir);
if (!hasValidPlugins(marketplace)) {
  throw new Error('marketplace.json must contain a non-empty plugins array');
}

Type guard

/**
 * @param {*} data
 * @returns {data is { plugins: Array<{name: string}> }}
 */
function isValidMarketplace(data) {
  return data != null && typeof data === 'object' &&
    Array.isArray(data.plugins) && data.plugins.length > 0;
}

Try / catch

try {
  const modules = await mgr.discoverModules(marketplaceData, sourceUrl);
} catch (e) {
  if (e.message === 'marketplace.json contains no plugins') {
    console.error('The marketplace.json has no plugins. Check the file structure or remove it to use direct install mode.');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling discoverModules() with marketplaceData parsed from a .claude-plugin/marketplace.json that has no 'plugins' key, has plugins set to null/empty object, or has plugins: []. This happens during resolveSource() when the cloned repo's marketplace.json is read and mode is set to 'discovery'.

Common situations: A repository has a .claude-plugin/marketplace.json scaffold file that was never populated; the plugins key was renamed (e.g., 'modules'); JSON was manually edited and the array was emptied; the file is a valid JSON but a different schema than expected.

Related errors


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