withastro/astro · warning

${colors.bold(plugin[0])} not applied.

Error message

${colors.bold(plugin[0])} not applied.

What it means

Same MDX string-plugin filter as the bare-string case, but for the tuple form: an entry like ['remark-gfm', {option: true}] whose first element is a string. ignoreStringPlugins() treats a tuple with a string head exactly like a bare string, because the plugin implementation still cannot be resolved by name in the MDX compile pipeline, and drops the whole tuple including its options.

Source

Thrown at packages/integrations/mdx/src/utils.ts:96

			// @ts-expect-error `parse` return types is incompatible but it should work in runtime
			estree: {
				...parse(jsString, acornOpts),
				type: 'Program',
				sourceType: 'module',
			},
		},
	};
}

export function ignoreStringPlugins(plugins: any[], logger: AstroIntegrationLogger): PluggableList {
	let validPlugins: PluggableList = [];
	let hasInvalidPlugin = false;
	for (const plugin of plugins) {
		if (typeof plugin === 'string') {
			logger.warn(`${colors.bold(plugin)} not applied.`);
			hasInvalidPlugin = true;
		} else if (Array.isArray(plugin) && typeof plugin[0] === 'string') {
			logger.warn(`${colors.bold(plugin[0])} not applied.`);
			hasInvalidPlugin = true;
		} else {
			validPlugins.push(plugin);
		}
	}
	if (hasInvalidPlugin) {
		logger.warn(
			`To inherit Markdown plugins in MDX, please use explicit imports in your config instead of "strings." See Markdown docs: https://docs.astro.build/en/guides/markdown-content/#markdown-plugins`,
		);
	}
	return validPlugins;
}

View on GitHub (pinned to 52e6c34790)

Solutions

  1. Import the plugin function and keep it as the tuple head: import rehypeExternalLinks from 'rehype-external-links'; rehypePlugins: [[rehypeExternalLinks, { target: '_blank' }]].
  2. Repeat for every tuple whose first element is a string until the warning stops on build.
  3. Run astro build or astro dev and verify the follow-up 'To inherit Markdown plugins in MDX...' warning no longer appears.

Example fix

// before
import defineConfig from 'astro/config';
export default defineConfig({
  markdown: { rehypePlugins: [['rehype-external-links', { target: '_blank' }]] },
});

// after
import rehypeExternalLinks from 'rehype-external-links';
export default defineConfig({
  markdown: { rehypePlugins: [[rehypeExternalLinks, { target: '_blank' }]] },
});
Defensive patterns

Strategy: type-guard

Validate before calling

const isTuplePlugin = (p: unknown): boolean =>
  Array.isArray(p) && typeof p[0] === 'function';
const badTuples = plugins.filter((p) => Array.isArray(p) && typeof p[0] !== 'function');

Type guard

const isPluginWithOptions = (
  p: unknown,
): p is [Plugin, Record<string, unknown>] =>
  Array.isArray(p) && typeof p[0] === 'function' && typeof p[1] === 'object';

Prevention

When it happens

Trigger: markdown.remarkPlugins or markdown.rehypePlugins contains an Array whose [0] is a string, e.g. rehypePlugins: [['rehype-external-links', { target: '_blank' }]], with @astrojs/mdx installed. The Array.isArray(plugin) && typeof plugin[0] === 'string' branch fires and the entry is excluded from validPlugins.

Common situations: Migrating configs that used the ['plugin-name', options] string-tuple convention; option-carrying plugins (autolink headings, external links, katex) defined by name; presets copied from unified/remark documentation that allow string require-style references.

Related errors


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