vitejs/vite · error · Error
external must be an array
Error message
external must be an array
What it means
Thrown by the externalizeDepsInWatchPlugin in Vite's own rolldown build config when running in watch mode. The plugin attempts to concatenate devDependencies onto options.external, but Rollup/Rolldown allows external to be a function (not just an array). If the resolved config's external is a function or a non-array value, this assertion fires. This error is internal to building Vite itself, not consumer application builds.
Source
Thrown at packages/vite/rolldown.config.ts:215
"export * from '../../src/node/index.ts'",
)
writeFileSync(
'dist/node/module-runner.d.ts',
"export * from '../../src/module-runner/index.ts'",
)
}
},
}
}
function externalizeDepsInWatchPlugin(): Plugin {
return {
name: 'externalize-deps-in-watch',
options(options) {
if (this.meta.watchMode) {
options.external ||= []
if (!Array.isArray(options.external))
throw new Error('external must be an array')
options.external = options.external.concat(
Object.keys(pkg.devDependencies),
)
}
},
}
}
interface ShimOptions {
src?: string
replacement: string
pattern?: RegExp
}
function shimDepsPlugin(deps: Record<string, ShimOptions[]>): Plugin {
const transformed: Record<string, boolean> = {}
return {View on GitHub (pinned to 89620f09af)
Solutions
- If you modified nodeConfig.external to a function, convert the externalizeDepsInWatchPlugin logic to handle function externals (wrap the function).
- Keep options.external as an array in the base config; the watch-mode plugin only supports arrays.
- If you hit this without modifying Vite's source, ensure you're using the correct build scripts.
Example fix
// before — external is a function
external: (id) => id.includes('node:')
// after — the watch plugin needs an array; wrap instead
const baseExternal = [...Object.keys(pkg.dependencies)]
external: [
...baseExternal,
// add function-based externals as regex patterns instead
] Defensive patterns
Strategy: validation
Validate before calling
// For Vite contributors: validate external is an array before watch-mode concatenation
function ensureArrayExternal(options) {
if (options.external && !Array.isArray(options.external)) {
throw new TypeError('options.external must be an array for watch-mode devDependencies injection')
}
} Type guard
function isArrayExternal(external: unknown): external is string[] | RegExp[] {
return Array.isArray(external)
} Try / catch
// In the plugin, handle function externals gracefully
if (!Array.isArray(options.external)) {
if (typeof options.external === 'function') {
const fn = options.external
const deps = Object.keys(pkg.devDependencies)
options.external = (id) => fn(id) || deps.includes(id)
} else {
throw new Error('external must be an array')
}
} Prevention
- When contributing to Vite, keep nodeConfig.external as an array, not a function.
- If you need function-based externals, modify externalizeDepsInWatchPlugin to wrap them.
- Run the watch build after any external config changes.
When it happens
Trigger: Running Vite's own build in watch mode (e.g., pnpm dev or the rolldown build with --watch) when the nodeConfig's external field has been changed from an array to a function or another type by a code change in rolldown.config.ts.
Common situations: A contributor to Vite's codebase modifies the external field in nodeConfig to use a function for more sophisticated externals resolution, then runs the dev/watch build. This is a development-time error for Vite contributors, not end users.
Related errors
- Unsupported output format ${outputOptions.format}
- Could not find original file for ${prefix}${index} in ${chun
- [vite]: Rolldown failed to resolve import "${exporter}" from
AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03).
Data as JSON: /data/errors/50c9e15bb7c2cdee.json.
Report an issue: GitHub.