vitejs/vite · error · Error

There is already a server associated with the config.

Error message

There is already a server associated with the config.

What it means

createServer at packages/vite/src/node/server/index.ts:505 keeps a WeakMap (usedConfigs) from resolved config objects to the dev server they back. Calling createServer twice with the same ResolvedConfig instance throws, because a config is meant to back at most one server and the second call would share mutable state (plugins, caches) in unsafe ways.

Source

Thrown at packages/vite/src/node/server/index.ts:505

  inlineConfig: ResolvedConfig | InlineConfig | undefined = {},
  options: {
    listen: boolean
    previousEnvironments?: Record<string, DevEnvironment>
    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,

View on GitHub (pinned to 89620f09af)

Solutions

  1. Resolve a fresh config for each server (pass an InlineConfig, not a ResolvedConfig) so createServer resolves internally.
  2. Call server.close() on the previous server before creating a new one — and still pass a freshly resolved config.
  3. If you must reuse config, deep-clone it before each createServer call so usedConfigs sees a different object.

Example fix

// before
const config = await resolveConfig({}, 'serve')
const s1 = await createServer(config)
const s2 = await createServer(config) // throws

// after
const s1 = await createServer({})
const s2 = await createServer({})
Defensive patterns

Strategy: validation

Validate before calling

import { isResolvedConfig, type InlineConfig } from 'vite'
function assertConfigUsable(config: unknown) {
  // pass InlineConfig to createServer; never reuse a ResolvedConfig across servers.
  if (isResolvedConfig(config)) {
    throw new Error('Pass an InlineConfig to createServer, or re-resolve for a fresh object')
  }
}

Prevention

When it happens

Trigger: Awaiting resolveConfig once and passing the result to createServer in two places; a test helper that calls createServer(config) without re-resolving; restarting logic that reuses the previously resolved config instead of resolving a fresh one.

Common situations: Custom harnesses caching the resolved config; integration tests sharing fixtures; frameworks that call createServer internally after the user already did.

Related errors


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