withastro/astro · error · MarkdocError
**${relativePartialPath}** contains invalid content: Could n
Error message
**${relativePartialPath}** contains invalid content:
Could not read partial file `${file}`. Does the file exist? What it means
During partial resolution the integration tries to resolve the `file` value via the Rolldown plugin context (`pluginContext.resolve`), falls back to `./` + file, and reads the resolved path with `fs.promises.readFile`. If resolution returns no id or reading throws, a `MarkdocError` is raised naming the partial and noting the file may not exist.
Source
Thrown at packages/integrations/markdoc/src/content-entry-type.ts:202
let partialPath: string;
let partialContents: string;
try {
const resolved = await pluginContext.resolve(file, fileURLToPath(fileUrl));
let partialId = resolved?.id;
if (!partialId) {
const attemptResolveAsRelative = await pluginContext.resolve(
'./' + file,
fileURLToPath(fileUrl),
);
if (!attemptResolveAsRelative?.id) throw new Error();
partialId = attemptResolveAsRelative.id;
}
partialPath = fileURLToPath(new URL(prependForwardSlash(partialId), 'file://'));
partialContents = await fs.promises.readFile(partialPath, 'utf-8');
} catch {
throw new MarkdocError({
message: [
`**${String(relativePartialPath)}** contains invalid content:`,
`Could not read partial file \`${file}\`. Does the file exist?`,
].join('\n'),
});
}
if (pluginContext.meta.watchMode) pluginContext.addWatchFile(partialPath);
let partialTokens = tokenizer.tokenize(partialContents);
if (allowHTML) {
partialTokens = htmlTokenTransform(tokenizer, partialTokens);
}
const partialAst = Markdoc.parse(partialTokens);
raisePartialValidationErrors(partialAst, partialPath);
await resolvePartials({
ast: partialAst,
root,
fileUrl: pathToFileURL(partialPath),
tokenizer,View on GitHub (pinned to d081033d5f)
Solutions
- Verify the partial file exists at the path declared in `file=`.
- Use a path that resolves relative to the `.mdoc` file importing it (prefix with `./` if needed).
- Check filesystem case matches exactly on case-sensitive build environments.
- Confirm the partial is inside the Astro project root or an allowed Vite dir.
Example fix
{% partial file="./_nav.mdoc" / %} Defensive patterns
Strategy: validation
Validate before calling
import { pathExists } from 'fs-extra';
async function partialExists(file: string, from: string) {
const resolved = path.resolve(path.dirname(from), file);
return await pathExists(resolved);
} Type guard
async function canReadPartial(file: string, baseDir: string): Promise<boolean> {
try {
await fs.promises.access(path.resolve(baseDir, file));
return true;
} catch { return false; }
} Try / catch
try {
await resolvePartial(file, fileUrl);
} catch (e) {
console.error(`Could not read partial ${file} from ${fileUrl}`);
throw e;
} Prevention
- Reference partials with explicit relative paths (`./name.mdoc`).
- Run `astro check` / Markdoc validation locally before push.
- Keep partials inside the project root.
When it happens
Trigger: Referencing `{% partial file="./missing.mdoc" / %}` where the file does not exist on disk. Path that cannot be resolved by Rolldown/Vite from the importing `.mdoc`'s location. Symlink or permission issue during read. Partial path is absolute or non-relative and resolve fails both attempts.
Common situations: Typo in the partial path. Moved/deleted a partial without updating references. Importing a partial from a directory not covered by Vite's `fs.allow`. Case-sensitivity mismatch between macOS dev and Linux build.
Related errors
- CannotDetermineWeightAndStyleFromFontFile
- UnknownFilesystemError
- UnknownFilesystemError
- UnknownFilesystemError
- Failed to write lock file: ${message}
AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12).
Data as JSON: /api/errors/3084d34d54af5955.
Report an issue: GitHub.