withastro/astro · warning
More than one JSX renderer is enabled. This will lead to une
Error message
More than one JSX renderer is enabled. This will lead to unexpected behavior unless you set the `include` or `exclude` option. See https://docs.astro.build/en/guides/integrations-guide/solid-js/#combining-multiple-jsx-frameworks for more information.
What it means
When the Vue integration is configured with `jsx: true`, Vue itself becomes a JSX renderer competing with other JSX-based renderers. In its `astro:config:done` hook (packages/integrations/vue/src/index.ts:220) it checks `config.integrations` for more than one of @astrojs/react, @astrojs/preact, @astrojs/solid-js; if two or more are present and you passed neither `include` nor `exclude` to the Vue integration, it warns that JSX files may be compiled by the wrong framework. Without include/exclude globs, every `.jsx/.tsx` file goes through whichever renderer Vite resolves first, so a Solid page can silently render with React's `createElement` (or vice versa), producing broken hydration or runtime errors.
Source
Thrown at packages/integrations/vue/src/index.ts:220
hooks: {
'astro:config:setup': async ({ addRenderer, updateConfig, command }) => {
addRenderer(getContainerRendererImpl());
if (options?.jsx) {
addRenderer(getJsxRenderer());
}
updateConfig({ vite: await getViteConfiguration(command, options) });
},
'astro:config:done': ({ logger, config }) => {
if (!options?.jsx) return;
const knownJsxRenderers = ['@astrojs/react', '@astrojs/preact', '@astrojs/solid-js'];
const enabledKnownJsxRenderers = config.integrations.filter((renderer) =>
knownJsxRenderers.includes(renderer.name),
);
// This error can only be thrown from here since Vue is an optional JSX renderer
if (enabledKnownJsxRenderers.length > 1 && !options?.include && !options?.exclude) {
logger.warn(
'More than one JSX renderer is enabled. This will lead to unexpected behavior unless you set the `include` or `exclude` option. See https://docs.astro.build/en/guides/integrations-guide/solid-js/#combining-multiple-jsx-frameworks for more information.',
);
}
},
},
};
}
View on GitHub (pinned to 52e6c34790)
Solutions
- Scope the Vue JSX rendering with include/exclude globs so each JSX variant only compiles its own files, e.g. `vue({ jsx: true, include: ['**/*.vue', '**/*.jsx'] })` combined with equivalent `include` on the other renderers.
- If you no longer need one of the JSX frameworks, remove its integration from `astro.config` and uninstall the package — the conflict disappears.
- Use file extensions or directory conventions to partition frameworks (e.g. `.tsx` for React under `src/react/`, `.jsx` for Vue under `src/vue/`) and reflect them in each renderer's include/exclude, per the linked solid-js guide.
Example fix
// before
import vue from '@astrojs/vue';
import react from '@astrojs/react';
import solid from '@astrojs/solid-js';
export default defineConfig({
integrations: [vue({ jsx: true }), react(), solid()],
});
// after
export default defineConfig({
integrations: [
vue({ jsx: true, include: ['**/*.vue', '**/vue/**/*.jsx'] }),
react({ include: ['**/*.tsx', '**/react/**'] }),
solid({ include: ['**/solid/**'] }),
],
}); Defensive patterns
Strategy: validation
Validate before calling
// sanity-check the resolved Astro config before building
// (run via `astro config`-style inspection or by loading the config with the Astro CLI)
const jsxRenderers = config.integrations
.map((i) => i.name)
.filter((n) => ['@astrojs/react', '@astrojs/preact', '@astrojs/solid-js'].includes(n));
const vueOptionsIncludeExclude = /* your vue() include/exclude options */;
if (jsxRenderers.length > 1 && !vueOptionsIncludeExclude) {
throw new Error('Set include/exclude on vue({ jsx: true }) — multiple JSX renderers enabled');
} Prevention
- Whenever more than one JSX-capable integration is installed, always set `include` (or `exclude`) on every one of them — an unscoped JSX renderer is the actual defect the warning points at.
- Adopt a directory or extension convention per framework (e.g. `src/react/**/*.tsx` vs `src/solid/**/*.tsx`) and encode it in each integration's include globs.
- Remove integrations for frameworks you no longer render; 'just in case' integrations are what create silent wrong-renderer compilation.
- Smoke-test one component per framework after config changes — wrong-renderer JSX usually breaks hydration rather than the build itself.
When it happens
Trigger: `astro.config.mjs` has `vue({ jsx: true })` (or the JSX option enabled) AND at least two of @astrojs/react, @astrojs/preact, @astrojs/solid-js are in `integrations`, AND the Vue integration options contain neither `include` nor `exclude`. The check runs once during `astro dev`/`astro build` startup in `astro:config:done`. Note Vue is special-cased as the only place this can warn, because it is an optional JSX renderer; if only one other JSX renderer is enabled, no warning fires.
Common situations: A mixed-framework design-system or migration repo (e.g. incrementally moving React pages to Solid while both integrations stay installed) that also adds Vue with JSX support; monorepos where a shared config file lists many integrations; adding a new JSX framework dependency for one component without removing the old integration from the config.
Related errors
- More than one JSX renderer is enabled. This will lead to une
- More than one JSX renderer is enabled. This will lead to une
- More than one JSX renderer is enabled. This will lead to une
- Unsupported React version: ${majorVersion}.
- [@astrojs/vue] Importing `getContainerRenderer` from `@astro
AI-assisted analysis of withastro/astro@52e6c34790 (2026-08-18).
Data as JSON: /api/errors/e4fa8e8d430d50a4.
Report an issue: GitHub.