withastro/astro · error · MarkdocError

(Uncaught error) Partial tag requires a 'file' attribute

Error message

(Uncaught error) Partial tag requires a 'file' attribute

What it means

The Markdoc integration walks a document's AST to resolve `{% partial %}` tags, which must carry a `file` attribute naming the partial to inline. A partial node without `file` has nothing to resolve, so the walker throws this MarkdocError (normally the earlier Markdoc validation pass catches it first — this is the safety net).

Solutions

  1. Add the required attribute: `{% partial file="headers/banner" /%}`.
  2. Check for typos in the attribute name (`file`, not `path`/`filepath`/`src`).
  3. If you meant a custom container, rename your tag to something other than `partial` in the Markdoc config.

Example fix

{% partial /%}

{% partial file="partials/nav" /%}
Defensive patterns

Strategy: validation

Validate before calling

// Lint .mdoc sources before build: every {% partial %} must carry file="..."
import { Markdoc } from '@markdoc/markdoc';
import { globSync } from 'glob';
import fs from 'node:fs';
for (const f of globSync('src/**/*.mdoc')) {
  for (const node of Markdoc.parse(fs.readFileSync(f, 'utf8')).walk()) {
    if (node.type === 'tag' && node.tag === 'partial' && !node.attributes.file) {
      throw new Error(`${f}: {% partial %} missing required "file" attribute`);
    }
  }
}

Prevention

When it happens

Trigger: Writing `{% partial /%}` (or `{% partial %}...{% /partial %}`) in a .mdoc/Markdoc content file without a `file` attribute.

Common situations: Typos like `filepath=` or missing quotes around the attribute; copy-pasting partial examples from docs of other template engines; partial wrappers intended to nest content but mistakenly using the reserved `partial` tag name.

Related errors


AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18). Data as JSON: /api/errors/f1f4f0142d43191d. Report an issue: GitHub.

Appendix: source

Thrown at packages/integrations/markdoc/src/content-entry-type.ts:177

	markdocConfig,
	pluginContext,
	raisePartialValidationErrors,
}: {
	ast: Node;
	fileUrl: URL;
	root: URL;
	tokenizer: any;
	allowHTML?: boolean;
	markdocConfig: MarkdocConfig;
	pluginContext: Rolldown.PluginContext;
	raisePartialValidationErrors: (ast: Node, filePath: string) => void;
}) {
	const relativePartialPath = path.relative(fileURLToPath(root), fileURLToPath(fileUrl));
	for (const node of ast.walk()) {
		if (node.type === 'tag' && node.tag === 'partial') {
			const { file } = node.attributes;
			if (!file) {
				throw new MarkdocError({
					// Should be caught by Markdoc validation step.
					message: `(Uncaught error) Partial tag requires a 'file' attribute`,
				});
			}

			if (markdocConfig.partials?.[file]) continue;

			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();

View on GitHub (pinned to 52e6c34790)