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
- Open the source repository's .claude-plugin/marketplace.json and add a non-empty 'plugins' array with at least one plugin object.
- Verify the JSON structure matches the expected schema: { "plugins": [ { "name": "...", "skills": [...] } ] }.
- 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
- Validate marketplace.json structure with a JSON schema before feeding it to discoverModules.
- Use a schema validator like ajv to check the plugins array is present and non-empty.
- Provide a template marketplace.json for module authors to follow.
- Test with a known-good marketplace.json during development.
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.