withastro/astro · error · AstroError

InvalidFrontmatterInjectionError

InvalidFrontmatterInjectionError

Error message

A remark or rehype plugin attempted to inject invalid frontmatter. Ensure "astro.frontmatter" is set to a valid JSON object that is not `null` or `undefined`.

What it means

Thrown (code `InvalidFrontmatterInjectionError`) after Markdown rendering when a remark or rehype plugin has set `astro.frontmatter` on the file data to something that is not a valid JSON-serializable object — i.e. null or undefined. The plugin validates `renderResult.metadata.frontmatter` with `isFrontmatterValid` before continuing; injected frontmatter must be a plain object.

Source

Thrown at packages/astro/src/vite-plugin-markdown/index.ts:98

				if (!renderer) {
					const { markdown: md, image } = settings.config;
					renderer = md.processor.createRenderer({
						image,
						syntaxHighlight: md.syntaxHighlight,
						shikiConfig: md.shikiConfig,
						gfm: md.gfm,
						smartypants: md.smartypants,
					});
				}

				const renderResult = await (await renderer).render(raw.content, {
					fileURL,
					frontmatter: raw.frontmatter,
				});

				// Improve error message for invalid astro frontmatter
				if (!isFrontmatterValid(renderResult.metadata.frontmatter)) {
					throw new AstroError(AstroErrorData.InvalidFrontmatterInjectionError);
				}

				let html = renderResult.code;
				const {
					headings,
					localImagePaths: rawLocalImagePaths,
					remoteImagePaths,
					frontmatter,
				} = renderResult.metadata;

				// Add default charset for markdown pages
				const isMarkdownPage = isPage(fileURL, settings);
				const charset = isMarkdownPage ? '<meta charset="utf-8">' : '';

				// Resolve all the extracted images from the content
				const localImagePaths: MarkdownImagePath[] = [];
				for (const imagePath of rawLocalImagePaths) {
					localImagePaths.push({

View on GitHub (pinned to d081033d5f)

Solutions

  1. Ensure your remark/rehype plugin sets frontmatter to a plain object: `file.data.astro.frontmatter = { ...existing, myKey: 'value' }`.
  2. Never assign null/undefined; if you have nothing to inject, leave the key unset or assign `{}`.
  3. Spread the existing frontmatter to avoid clobbering other plugins' injections.

Example fix

// before — remark plugin
export function myRemark() {
  return (tree, file) => {
    file.data.astro.frontmatter = null;
  };
}

// after
export function myRemark() {
  return (tree, file) => {
    file.data.astro.frontmatter = { ...(file.data.astro.frontmatter || {}), myKey: 'value' };
  };
}
Defensive patterns

Strategy: validation

Validate before calling

function isFrontmatterValid(fm) {
  return fm !== null && fm !== undefined && typeof fm === 'object' && !Array.isArray(fm);
}

Type guard

function isValidFrontmatter(fm): fm is Record<string, unknown> {
  return typeof fm === 'object' && fm !== null && !Array.isArray(fm);
}

Prevention

When it happens

Trigger: A custom remark/rehype plugin assigns `file.data.astro.frontmatter = null`, `= undefined`, `= 'string'`, or deletes the key during Markdown processing. Astro's Markdown renderer collects that injected data and the post-render check fails.

Common situations: Writing a remark plugin that conditionally sets frontmatter and forgets to initialize the object. A plugin mutating `file.data.astro.frontmatter` to a non-object. Combining community remark plugins that conflict over frontmatter injection.

Related errors


AI-assisted analysis of withastro/astro@d081033d5f (2026-08-12). Data as JSON: /api/errors/8d97e45063271435. Report an issue: GitHub.