bmad-code-org/BMAD-METHOD · error · Error
Subdirectory '${parsed.subdir}' not found in cloned reposito
Error message
Subdirectory '${parsed.subdir}' not found in cloned repository What it means
Thrown by resolveSource() after a successful clone when the URL contained a subdirectory reference (via /tree/<ref>/<subdir> or ?path=/subdir) but that subdirectory does not exist inside the cloned repository. The check uses fs.pathExists on path.join(repoPath, subdir).
Source
Thrown at tools/installer/modules/custom-module-manager.js:347
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`);
}
}
const marketplace = await this.readMarketplaceJsonFromDisk(rootDir);
const mode = marketplace ? 'discovery' : 'direct';
return { parsed, rootDir, repoPath, sourceUrl, marketplace, mode };
}
// ─── Clone ────────────────────────────────────────────────────────────────
/**
* Get the cache directory for custom modules.
* @returns {string} Path to the custom modules cache directory
*/
getCacheDir() {
return path.join(os.homedir(), '.bmad', 'cache', 'custom-modules');
}View on GitHub (pinned to b70486b9bd)
Solutions
- Open the repository in a browser at the cloned ref and verify the subdirectory path exists.
- Remove the subdirectory from the URL to clone the whole repo, then navigate to the correct path.
- Pin to a version/tag where the subdirectory is known to exist.
Example fix
// before
await mgr.resolveSource('https://github.com/org/repo/tree/main/src/old-folder');
// after
await mgr.resolveSource('https://github.com/org/repo/tree/main/src/new-folder');
// or clone entire repo:
await mgr.resolveSource('https://github.com/org/repo'); Defensive patterns
Strategy: validation
Validate before calling
// After cloning, verify subdir exists before relying on it
const parsed = mgr.parseSource(url);
if (parsed.subdir) {
// You can't check before clone, but you can pre-validate by listing remote refs
console.log(`Will expect subdirectory: ${parsed.subdir}`);
// After resolveSource succeeds, the subdir is guaranteed to exist
} Try / catch
try {
const result = await mgr.resolveSource(url);
} catch (e) {
if (e.message.includes('not found in cloned repository')) {
// Retry without the subdirectory to clone the whole repo
const urlWithoutSubdir = url.replace(/\/tree\/[^/]+\/.*$/, '');
console.log(`Retrying full repo clone: ${urlWithoutSubdir}`);
await mgr.resolveSource(urlWithoutSubdir);
return;
}
throw e;
} Prevention
- Verify the subdirectory path exists in the target branch before using a deep-link URL.
- Prefer cloning the whole repo over using subdirectory deep-links when unsure.
- Pin to a tag where the subdirectory is known to exist.
When it happens
Trigger: Cloning a URL like https://github.com/org/repo/tree/main/src/old-folder where 'src/old-folder' was deleted or renamed after the referenced ref. Also when a deep-path URL points at a path that only exists on a different branch.
Common situations: The repository was restructured and the subdirectory moved or removed; the user copied a deep-link URL from a different branch; the /tree/ path segment was misinterpreted during parsing.
Related errors
- Failed to clone ${parsed.cloneUrl}${refSuffix}: ${error_.mes
- Failed to clone external module '${moduleCode}' at ${resolve
- ${label} does not exist: ${dirPath}
- ${label} is not a directory: ${dirPath}
- ${label} is not readable: ${dirPath}
AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13).
Data as JSON: /api/errors/5272c575933145d5.
Report an issue: GitHub.