cypress-io/cypress · error · Error
${err}
Error message
${err} What it means
The catch-all in devServer.create: it wraps the createServer/createViteDevServerConfig phase. If the thrown value is already an Error it is rethrown unchanged; any non-Error value (string, object, plain rejection) is coerced via `new Error(err as string)`. So the surfaced message is whatever non-Error value the underlying Vite/config pipeline rejected with, stringified.
Source
Thrown at npm/vite-dev-server/src/devServer.ts:119
devServer.create = async function createDevServer (devServerConfig: ViteDevServerConfig, vite: Vite_7 | Vite_8) {
try {
// Handling here is mainly for conditional generics to make sure we get the types correct between vite 7 and vite 8.
// Eventually, vite 8 will be the default and we can remove this logic
if (isVite8(vite)) {
const config = await createViteDevServerConfig<Vite_8>(devServerConfig, vite as Vite_8)
return await (vite as Vite_8).createServer(config)
}
const config = await createViteDevServerConfig<Vite_7>(devServerConfig, vite as Vite_7)
return await (vite as Vite_7).createServer(config)
} catch (err) {
if (err instanceof Error) {
throw err
}
throw new Error(err as string)
}
}
View on GitHub (pinned to 0d85fdc912)
Solutions
- Inspect the embedded message — it is the raw stringified rejection from the Vite pipeline.
- Reproduce the viteConfig outside Cypress with `vite` directly to isolate whether the fault is in your config or in Cypress's wrapping.
- Ensure any custom Vite plugins throw real Errors (with stack traces), not strings, for diagnosable output.
- Align your installed Vite major (5/6/7/8) with plugin compatibility.
Example fix
// before: plugin throws a string
const myPlugin = () => ({ name: 'p', transform () { throw 'bad input' } })
// after: throw a real Error
const myPlugin = () => ({ name: 'p', transform () { throw new Error('bad input') } }) Defensive patterns
Strategy: try-catch
Type guard
const isRealError = (e: unknown): e is Error => e instanceof Error
Try / catch
try {
await devServer.create(devServerConfig, vite)
} catch (err) {
const e = err instanceof Error ? err : new Error(String(err))
// log e, decide retry vs fail
throw e
} Prevention
- Make custom Vite plugins throw real Errors with stack traces.
- Validate viteConfig shape before passing to devServer.
- Reproduce config failures with plain vite outside Cypress to isolate causes.
When it happens
Trigger: Any failure inside vite.createServer(config) or createViteDevServerConfig — e.g. an invalid plugin, a config that throws a string, an ESM/CJS interop rejection, or a plugin that rejects with a plain object rather than an Error. The wrapper ensures Cypress always rethrows a real Error.
Common situations: A user Vite plugin that throws a string instead of an Error; a viteConfig function that returns an invalid shape; a config import that fails to resolve; version skew between installed Vite and a plugin expecting a different API.
Related errors
- Missing vite dev server port.
- CJS builds of vite ${majorVersionNumber} are not supported
- Could not find "vite" in your project's dependencies. Please
- Your component devServer config for vite is missing a requir
- ESM plugin config value '${name}' must be an array of string
AI-assisted analysis of cypress-io/cypress@0d85fdc912 (2026-08-12).
Data as JSON: /api/errors/b3b6dcd12ad58c09.
Report an issue: GitHub.