vitejs/vite · error · Error
invalid rolldownOptions.input value.
Error message
invalid rolldownOptions.input value.
What it means
Thrown by `computeEntries` when `rolldownOptions.input` is set but is neither a string, an array, nor a plain object — the three shapes the resolver knows how to iterate. scan.ts:244 throws unconditionally for any other type (e.g. number, function, null after a truthy check passes).
Solutions
- Set `build.rolldownOptions.input` to a string, an array of strings, or a record `{ name: path }`.
- Resolve dynamic input to a concrete array before returning config.
- If you need code-splitting entry objects, use the `{ [name]: path }` form.
- Type-check the config (`vite config` / `tsc`) to catch shape errors before run.
Example fix
// before
export default defineConfig({
build: { rollupOptions: { input: () => findEntries() } }, // function unsupported
})
// after
const entries = await findEntries()
export default defineConfig({
build: { rollupOptions: { input: entries } }, // string[]
}) Defensive patterns
Strategy: type-guard
Validate before calling
function assertInputShape(input: unknown) {
if (typeof input !== 'string' && !Array.isArray(input) && (typeof input !== 'object' || input === null || Array.isArray(input) || input instanceof Map || typeof input === 'function')) {
throw new TypeError('rolldownOptions.input must be string, string[], or Record<string,string>')
}
} Type guard
function isValidInput(v: unknown): v is string | string[] | Record<string, string> {
if (typeof v === 'string') return true
if (Array.isArray(v)) return v.every((x) => typeof x === 'string')
if (v && typeof v === 'object' && !(v instanceof Map) && typeof v !== 'function') {
return Object.values(v).every((x) => typeof x === 'string')
}
return false
} Try / catch
try {
await server.listen()
} catch (e) {
if (e instanceof Error && e.message === 'invalid rolldownOptions.input value.') {
console.error('rolldownOptions.input must be string, string[], or Record<string,string>; got', config.build.rolldownOptions.input)
}
throw e
} Prevention
- Type build.rolldownOptions.input with `as string | string[] | Record<string, string>` so the compiler catches bad shapes.
- Resolve dynamic input to concrete arrays before returning the config.
- Add a config-validation unit test that calls your defineConfig and asserts the input shape.
When it happens
Trigger: `build.rolldownOptions.input` (or `config.input`) is assigned a value of an unsupported type. The isObject check at scan.ts:241 passes for arrays-as-objects only via Array.isArray first; any other non-plain object (Map, function, class instance) falls through to line 244.
Common situations: Programmatic config that computes input dynamically and yields an unexpected type. Passing a Rollup-style `{ main: () => ... }` or a function. Misconfigured plugin that mutates input. Copy-paste from Rollup examples using unsupported shapes.
Related errors
- failed to resolve rolldownOptions.input value
- `input` cannot contain glob characters. They are reserved…
- config must export or return an object.
- Could not resolve " " imported by " ". Is it installed?
- currently full bundle mode is only available for client…
AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11).
Data as JSON: /api/errors/946847f8dfa3008f.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vite/src/node/optimizer/scan.ts:244
isEntry: true,
scan: true,
})
)?.id
if (id === undefined) {
throw new Error(
`failed to resolve rolldownOptions.input value: ${JSON.stringify(p)}.`,
)
}
return id
}
if (typeof input === 'string') {
entries = [await resolvePath(input)]
} else if (Array.isArray(input)) {
entries = await Promise.all(input.map(resolvePath))
} else if (isObject(input)) {
entries = await Promise.all(Object.values(input).map(resolvePath))
} else {
throw new Error('invalid rolldownOptions.input value.')
}
} else {
entries = await globEntries('**/*.html', environment)
}
// Non-supported entry file types and virtual files should not be scanned for
// dependencies.
entries = entries.filter(
(entry) =>
isScannable(entry, environment.config.optimizeDeps.extensions) &&
fs.existsSync(entry),
)
return entries
}
async function prepareRolldownScanner(
environment: ScanEnvironment,View on GitHub (pinned to b4d66fee14)