bmad-code-org/BMAD-METHOD · error · Error
Source is required
Error message
Source is required
What it means
Thrown by resolveSource() when parseSource() returns isValid:false with error 'Source is required'. This occurs when the input is null, undefined, not a string, or an empty/whitespace-only string.
Source
Thrown at tools/installer/modules/custom-module-manager.js:331
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;
let repoPath;
let sourceUrl;
if (parsed.type === 'local') {
rootDir = parsed.localPath;
repoPath = null;
sourceUrl = null;
} else {
repoPath = await this.cloneRepo(input, options);
sourceUrl = parsed.cloneUrl;
rootDir = parsed.subdir ? path.join(repoPath, parsed.subdir) : repoPath;
if (parsed.subdir && !(await fs.pathExists(rootDir))) {
throw new Error(`Subdirectory '${parsed.subdir}' not found in cloned repository`);
}
}View on GitHub (pinned to b70486b9bd)
Solutions
- Provide a non-empty string: either a Git URL (https://..., git@...) or a local filesystem path.
- Check that the variable holding the source string is initialized before calling resolveSource().
- If the source comes from user input, validate it is a non-empty string before proceeding.
Example fix
// before
const source = process.env.MODULE_URL; // undefined
await mgr.resolveSource(source);
// after
const source = process.env.MODULE_URL;
if (!source) throw new Error('MODULE_URL must be set');
await mgr.resolveSource(source); Defensive patterns
Strategy: validation
Validate before calling
if (!input || typeof input !== 'string' || input.trim().length === 0) {
throw new Error('A source URL or local path is required');
}
await mgr.resolveSource(input); Type guard
/**
* @param {*} input
* @returns {input is string}
*/
function isNonEmptyString(input) {
return typeof input === 'string' && input.trim().length > 0;
} Try / catch
try {
const result = await mgr.resolveSource(input);
} catch (e) {
if (e.message === 'Source is required') {
console.error('No source provided. Pass a Git URL or local path.');
return;
}
throw e;
} Prevention
- Always validate input is a non-empty string at the API boundary before calling resolveSource.
- Use default parameter values or early returns for missing CLI arguments.
- Log the variable name and value when debugging to identify which input is empty.
When it happens
Trigger: Calling resolveSource('') , resolveSource(null), resolveSource(undefined), or resolveSource(' ') (whitespace only). Also triggered if a variable that was expected to hold a URL/path is uninitialized when passed.
Common situations: A CLI flag was not provided (e.g., the install source argument was omitted); an environment variable read for the source came back undefined; a previous step failed to produce a URL and passed the empty result forward.
Related errors
- Unsafe ref name: ${JSON.stringify(ref)}
- Local paths do not support @version suffixes
- Not a valid Git URL or local path
- Path does not exist: ${resolved}
- Unsafe ref name: ${JSON.stringify(ref)}
AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13).
Data as JSON: /api/errors/ddfe97621322245a.
Report an issue: GitHub.