vitejs/vite · error · Error
`renderLegacyChunks` and `renderModernChunks` cannot be…
Error message
`renderLegacyChunks` and `renderModernChunks` cannot be both false
What it means
plugin-legacy has two independent toggles: `renderLegacyChunks` (default true) controls whether SystemJS-based legacy bundles are emitted, and `renderModernChunks` (default true) controls whether modern bundles/polyfills are emitted. Setting BOTH to false means the plugin would emit no output at all, which is an invalid configuration, so the plugin rejects it eagerly in `viteLegacyPlugin()`.
Solutions
- Remove the `legacy()` plugin from the Vite plugins array entirely if you want no legacy/modern processing.
- Keep at least one of the two flags at its default `true` (leave `renderModernChunks` unset while setting only `renderLegacyChunks: false`, or vice versa).
- If you only want polyfills without legacy SystemJS output, set `renderLegacyChunks: false` and provide `modernPolyfills` while leaving `renderModernChunks` at its default.
Example fix
// before
legacy({ renderLegacyChunks: false, renderModernChunks: false }),
// after - just drop the plugin
// (remove the `legacy(...)` line from plugins) Defensive patterns
Strategy: validation
Validate before calling
function validateLegacyOptions(opts: { renderLegacyChunks?: boolean; renderModernChunks?: boolean }) {
if (opts.renderLegacyChunks === false && opts.renderModernChunks === false) {
throw new Error('At least one of renderLegacyChunks/renderModernChunks must be true (or both left default).')
}
} Type guard
function isLegalLegacyOptions(o: unknown): boolean {
if (!o || typeof o !== 'object') return true
const { renderLegacyChunks, renderModernChunks } = o as any
return !(renderLegacyChunks === false && renderModernChunks === false)
} Prevention
- To disable legacy entirely, remove the legacy() plugin instead of flipping both flags.
- Only ever set ONE of the two flags to false; leave the other at its default.
When it happens
Trigger: Passing `{ renderLegacyChunks: false, renderModernChunks: false }` to `legacy()` in the Vite plugins array. This can happen when trying to use plugin-legacy purely for its polyfill detection while disabling both chunk kinds, or when conditionally computing flags that both evaluate to false.
Common situations: Trying to 'disable' plugin-legacy at runtime by flipping both flags to false instead of removing the plugin from the array. Copying an options object and toggling the wrong flag. Migrating between plugin versions where flag semantics changed.
Related errors
- @vitejs/plugin-legacy does not support library mode.
- Either "build.lib.entry" or the top-level "input" option is…
- No corresponding legacy entry chunk found for
- No corresponding legacy polyfill chunk found for
- No corresponding modern polyfill chunk found for
AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11).
Data as JSON: /api/errors/bf88837022859c96.
Report an issue: GitHub.
Appendix: source
Thrown at packages/plugin-legacy/src/index.ts:218
function resolveLegacyBuildMinify(
minify: BuildOptions['minify'],
supportsOxc: boolean | undefined,
): BuildOptions['minify'] {
const usesOxc = supportsOxc && (minify === 'oxc' || minify === true)
return usesOxc ? 'oxc' : minify ? 'terser' : false
}
function viteLegacyPlugin(options: Options = {}): Plugin[] {
let config: ResolvedConfig
let targets: Options['targets']
const modernTargets: Options['modernTargets'] =
options.modernTargets || modernTargetsBabel
const genLegacy = options.renderLegacyChunks !== false
const genModern = options.renderModernChunks !== false
if (!genLegacy && !genModern) {
throw new Error(
'`renderLegacyChunks` and `renderModernChunks` cannot be both false',
)
}
const debugFlags = (process.env.DEBUG || '').split(',')
const isDebug =
debugFlags.includes('vite:*') || debugFlags.includes('vite:legacy')
const assumptions = options.assumptions || {}
const facadeToLegacyChunkMap = new Map()
const facadeToLegacyImportMap = new Map<string | null, Rollup.OutputAsset>()
const facadeToLegacyPolyfillMap = new Map()
const facadeToModernPolyfillMap = new Map()
const modernPolyfills = new Set<string>()
const legacyPolyfills = new Set<string>()
// When discovering polyfills in `renderChunk`, the hook may be non-deterministic, so we group the
// modern and legacy polyfills in a sorted chunks map for each rendered outputs before merging them.View on GitHub (pinned to b4d66fee14)