vitejs/vite · error · Error
Config was resolved for a "build", expected a "serve" comman
Error message
Config was resolved for a "build", expected a "serve" command.
What it means
createServer at packages/vite/src/node/server/index.ts:509 asserts config.command === 'serve'. ResolvedConfig objects are bound to the command they were resolved for (build vs serve differ in plugin application, options, and defaults), so handing a build-resolved config to createServer would silently misbehave, hence the explicit throw.
Source
Thrown at packages/vite/src/node/server/index.ts:509
previousShortcutsState?: ShortcutsState<ViteDevServer>
previousRestartPromise?: Promise<void> | null
previousForceOptimizeOnRestart?: boolean
},
): Promise<ViteDevServer> {
// The dev server is a long-running, interactive process whose outputs
// (network responses, HMR updates) cannot be replayed from a cache.
disableCache()
const config = isResolvedConfig(inlineConfig)
? inlineConfig
: await resolveConfig(inlineConfig, 'serve')
if (usedConfigs.has(config)) {
throw new Error(`There is already a server associated with the config.`)
}
if (config.command !== 'serve') {
throw new Error(
`Config was resolved for a "build", expected a "serve" command.`,
)
}
usedConfigs.add(config)
const initPublicFilesPromise = initPublicFiles(config)
const { root, server: serverConfig } = config
const httpsOptions = await resolveHttpsConfig(config.server.https)
const { middlewareMode } = serverConfig
const resolvedOutDirs = getResolvedOutDirs(
config.root,
config.build.outDir,
config.build.rolldownOptions.output,
)
const emptyOutDir = resolveEmptyOutDir(View on GitHub (pinned to 89620f09af)
Solutions
- Let createServer resolve the config itself: pass an InlineConfig, not a ResolvedConfig.
- If you resolve manually, call resolveConfig(inlineConfig, 'serve') for the dev server.
- Re-resolve before each command instead of caching one ResolvedConfig across build and serve.
Example fix
// before
const config = await resolveConfig({}, 'build')
const server = await createServer(config)
// after
const server = await createServer({}) // resolves with 'serve'
// or:
const config = await resolveConfig({}, 'serve')
const server = await createServer(config) Defensive patterns
Strategy: validation
Validate before calling
function assertServeCommand(config: { command?: string }) {
if (config.command !== 'serve') {
throw new Error('createServer requires a config resolved with command "serve"')
}
} Type guard
function isServeConfig(config: { command?: string }): boolean {
return config.command === 'serve'
} Prevention
- Pass InlineConfig to createServer so it resolves with command='serve'.
- Call resolveConfig(..., 'serve') explicitly if you resolve manually.
- Re-resolve config per command rather than sharing one across build and serve.
When it happens
Trigger: Calling resolveConfig(inlineConfig, 'build') and passing that config to createServer; reusing a config resolved for `vite build` inside a dev script; library code that resolves config once and branches later.
Common situations: Building then previewing/dev-ing with the same resolved config; shared config utility that always resolves with 'build'; scripts that resolve config for inspection and then feed it to createServer.
Related errors
- `renderLegacyChunks` and `renderModernChunks` cannot be both
- Invalid environment name "${name}". Environment names must o
- HTTP server not available
- `input` cannot contain glob characters. They are reserved, s
- Required environments configuration were stripped out in the
AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03).
Data as JSON: /data/errors/027b786ffa498f31.json.
Report an issue: GitHub.