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
- Resolve a fresh config for each server (pass an InlineConfig, not a ResolvedConfig) so createServer resolves internally.
- Call server.close() on the previous server before creating a new one — and still pass a freshly resolved config.
- 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
- Pass InlineConfig to createServer and let Vite resolve it per server.
- Call server.close() and re-resolve config before starting a new server.
- Never cache a ResolvedConfig across multiple createServer calls.
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
- HTTP server not available
- multiple output options are not supported in dev mode
- Environment "${name}" is not defined in the config.
- Config was resolved for a "build", expected a "serve" comman
- Cannot print server URLs in middleware mode.
AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03).
Data as JSON: /data/errors/69cba91f46b82d8e.json.
Report an issue: GitHub.