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

  1. Let createServer resolve the config itself: pass an InlineConfig, not a ResolvedConfig.
  2. If you resolve manually, call resolveConfig(inlineConfig, 'serve') for the dev server.
  3. 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

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


AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03). Data as JSON: /data/errors/027b786ffa498f31.json. Report an issue: GitHub.