bmad-code-org/BMAD-METHOD · error · Error
[rehype-markdown-links] Could not detect content directory f
Error message
[rehype-markdown-links] Could not detect content directory for: ${currentFilePath} What it means
Thrown by the rehype-markdown-links plugin when detectContentDir can't find a content root for the current markdown file. detectContentDir walks the file's path segments looking for 'src/content/docs' (Astro/Starlight convention) or a standalone 'docs' directory; returning null means neither pattern matched, so the plugin cannot compute output URLs.
Source
Thrown at website/src/rehype-markdown-links.js:35
/**
* @param {Object} options
* @param {string} options.base - Site base path (e.g., '/BMAD-METHOD/')
* @param {string} [options.contentDir] - Absolute path to content root; auto-detected if omitted
*/
export default function rehypeMarkdownLinks(options = {}) {
const base = options.base || '/';
const normalizedBase = base === '/' ? '' : base.replace(/\/$/, '');
return (tree, file) => {
// The current file's absolute path on disk, set by Astro's markdown pipeline
const currentFilePath = file.path;
if (!currentFilePath) return;
// Auto-detect content root: walk up from current file to find src/content/docs
const contentDir = options.contentDir || detectContentDir(currentFilePath);
if (!contentDir) {
throw new Error(`[rehype-markdown-links] Could not detect content directory for: ${currentFilePath}`);
}
visit(tree, 'element', (node) => {
if (node.tagName !== 'a' || typeof node.properties?.href !== 'string') {
return;
}
const href = node.properties.href;
// Skip external links (including protocol-relative URLs like //cdn.example.com)
if (href.includes('://') || href.startsWith('//') || href.startsWith('mailto:') || href.startsWith('tel:')) {
return;
}
// Split href into path vs query+fragment suffix
const delimIdx = findFirstDelimiter(href);
const linkPath = delimIdx === -1 ? href : href.substring(0, delimIdx);
const suffix = delimIdx === -1 ? '' : href.substring(delimIdx);View on GitHub (pinned to b70486b9bd)
Solutions
- Pass contentDir explicitly in the plugin options: rehypeMarkdownLinks({ base, contentDir: '/abs/path/to/content' }).
- Ensure markdown files live under src/content/docs (Astro) or a docs/ directory so detectContentDir matches.
- If the site was restructured, update detectContentDir's pattern or the contentDir option to match the new layout.
Example fix
// before
// rehypeMarkdownLinks({ base }) // auto-detect fails on restructured site
//
// after
// rehypeMarkdownLinks({
// base,
// contentDir: path.resolve(process.cwd(), 'website/src/content/docs'),
// }) Defensive patterns
Strategy: validation
Validate before calling
const contentDir = options.contentDir || detectContentDir(currentFilePath);
if (!contentDir) {
throw new Error(`Configure rehypeMarkdownLinks({ contentDir: '...' }) for non-standard layouts.`);
}
// pass contentDir explicitly in the plugin options
rehypeMarkdownLinks({ base, contentDir }); Type guard
function hasContentDir(filePath) {
const seg = filePath.split(path.sep);
for (let i = seg.length - 1; i >= 2; i--) {
if (seg[i - 2] === 'src' && seg[i - 1] === 'content' && seg[i] === 'docs') return true;
}
return seg.includes('docs');
} Try / catch
try {
astroConfig.rehypePlugins.push([rehypeMarkdownLinks, { base, contentDir }]);
} catch (e) {
if (/Could not detect content directory/.test(e.message)) {
// fall back to explicit contentDir resolved from process.cwd()
} else { throw e; }
} Prevention
- Always pass contentDir explicitly when the site deviates from src/content/docs.
- Keep markdown under the recognized content root so auto-detection works.
- If you restructure content, update the plugin options in the same change.
When it happens
Trigger: Running the Astro build on a markdown file whose absolute path contains neither src/content/docs nor a docs segment. Calling the plugin outside its expected content-root layout (file.path is set, which skips the early return, but no recognized root is found above it).
Common situations: Restructuring the website content directory away from src/content/docs or docs; running the plugin against files outside the content root; build config changed srcDir; new collection location not covered by detectContentDir's patterns.
Related errors
- Obsolete implementation terminology found in deployable docu
- llms.txt must describe Build as canonical for both direct in
- Invalid GITHUB_REPOSITORY format: "${process.env.GITHUB_REPO
AI-assisted analysis of bmad-code-org/BMAD-METHOD@b70486b9bd (2026-08-13).
Data as JSON: /api/errors/5d31c40e4358a7a0.
Report an issue: GitHub.