withastro/astro · warning

[astro] `markdown.remarkPlugins`, `markdown.rehypePlugins`,

Error message

[astro] `markdown.remarkPlugins`, `markdown.rehypePlugins`, and `markdown.remarkRehype` are deprecated. Pass them to `unified({...})` from `@astrojs/markdown-remark` directly instead.

What it means

markdown.remarkPlugins, markdown.rehypePlugins, and markdown.remarkRehype are deprecated in favor of passing them to the unified({...}) processor from @astrojs/markdown-remark. While the unified processor is active, Astro still folds the legacy keys into it (plugins keep working, migration counts tracked per processor object) and prints this one-time warning.

Source

Thrown at packages/astro/src/core/config/validate.ts:108

		const target = (current ?? (md.processor = unified())) as ReturnType<typeof unified>;
		const counts = migratedLegacyPluginCounts.get(target.options) ?? { remark: 0, rehype: 0 };
		// Only push entries past what we've already folded; mergeConfig appends, so they sit at the tail.
		if (remarkPlugins.length > counts.remark) {
			target.options.remarkPlugins.push(...remarkPlugins.slice(counts.remark));
		}
		if (rehypePlugins.length > counts.rehype) {
			target.options.rehypePlugins.push(...rehypePlugins.slice(counts.rehype));
		}
		// `remarkRehype` is an object, so Object.assign is idempotent for unchanged keys
		// and absorbs any new keys integrations add.
		Object.assign(target.options.remarkRehype, remarkRehype);
		migratedLegacyPluginCounts.set(target.options, {
			remark: remarkPlugins.length,
			rehype: rehypePlugins.length,
		});
		if (!didWarnAboutLegacyMarkdownPlugins) {
			didWarnAboutLegacyMarkdownPlugins = true;
			console.warn(
				'[astro] `markdown.remarkPlugins`, `markdown.rehypePlugins`, and `markdown.remarkRehype` are deprecated. Pass them to `unified({...})` from `@astrojs/markdown-remark` directly instead.',
			);
		}
	} else if (!didWarnAboutProcessorMismatch) {
		// Third-party processors can't run remark/rehype plugins. And if they can, they should be passed directly to the processor (like it is for unified) instead of the legacy keys, so we warn either way.
		didWarnAboutProcessorMismatch = true;
		console.warn(
			`[astro] \`markdown.remarkPlugins\`/\`rehypePlugins\`/\`remarkRehype\` are set, but your ` +
				`\`${current.name}\` processor doesn't run them. Move them to \`unified({...})\` from ` +
				'`@astrojs/markdown-remark` and set `markdown.processor: unified({...})` if you want ' +
				'them to apply.',
		);
	}
}

/**
 * Used twice:
 * - To validate the user config

View on GitHub (pinned to 52e6c34790)

Solutions

  1. Replace the three keys with markdown: { processor: unified({ remarkPlugins: [...], rehypePlugins: [...], remarkRehype: {...} }) }
  2. Update third-party integrations that still write to the legacy keys
  3. Optionally leave them temporarily — behavior is preserved until the keys are removed in a future major

Example fix

// before
export default defineConfig({
  markdown: {
    remarkPlugins: [remarkToc],
    rehypePlugins: [rehypeSlug],
    remarkRehype: { clobberPrefix: 'user-content-' },
  },
});

// after
import { unified } from '@astrojs/markdown-remark';
export default defineConfig({
  markdown: {
    processor: unified({
      remarkPlugins: [remarkToc],
      rehypePlugins: [rehypeSlug],
      remarkRehype: { clobberPrefix: 'user-content-' },
    }),
  },
});
Defensive patterns

Strategy: validation

Validate before calling

// fail CI when legacy markdown plugin keys are set
const legacy = ['remarkPlugins', 'rehypePlugins', 'remarkRehype'];
const present = legacy.filter((k) => config.markdown?.[k] !== undefined);
if (present.length) throw new Error(`Move to processor config: ${present.join(', ')}`);

Prevention

When it happens

Trigger: The config (or an integration via updateConfig) sets any of markdown.remarkPlugins / markdown.rehypePlugins / markdown.remarkRehype while using the default unified processor; new integrations injecting plugins through the legacy keys re-trigger the fold each validate pass.

Common situations: Any pre-upgrade Astro project with remark/rehype plugins; popular integrations (e.g. MDX-related or documentation tooling) that still push into the legacy keys.

Related errors


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