vitest-dev/vitest · error · Error

Failed to load custom "defines

Error message

Failed to load custom "defines": ${error.message}

What it means

Vitest serializes config.define into a JS expression string (serializedDefines) and runs it via runInThisContext to inject global constants into the worker. If that generated JS fails to parse/evaluate, the original error is caught and re-thrown wrapped as 'Failed to load custom defines: <message>'. This runs in the base (non-vm) worker path.

Solutions

  1. Ensure every define value is JSON-serializable (strings, numbers, booleans, plain objects/arrays).
  2. Avoid functions, BigInt, circular references, and Symbols in test.define / vite.define.
  3. Read the wrapped error.message (the inner exception) to identify which define key broke.
  4. If you need runtime values, import them from a module instead of inlining via define.

Example fix

// before
export default defineConfig({
  test: { define: { __fn: () => 1 } }
})

// after
export default defineConfig({
  test: { define: { __flag: JSON.stringify('on') } }
})
Defensive patterns

Strategy: validation

Validate before calling

import { isJSON } from './checks'
function validateDefines(obj) {
  for (const [k, v] of Object.entries(obj)) {
    try { JSON.parse(JSON.stringify(v)) } catch { throw new Error(`define '${k}' is not serializable`) }
  }
}

Type guard

function isJsonSerializable(v) {
  try { JSON.stringify(v); return true } catch { return false }
}

Prevention

When it happens

Trigger: The define config produces values whose JSON serialization is not valid as the body of an IIFE in the worker context — e.g. a function, a circular object, a BigInt, or a value whose custom toJSON returns something unparseable. runInThisContext throws SyntaxError or TypeError, which gets wrapped.

Common situations: Putting non-serializable values in vitest.config define (functions, class instances, symbols), or a plugin mutating define at runtime to inject something that is not plain JSON.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/50c0eaeca8f6e8e2. Report an issue: GitHub.

Appendix: source

Thrown at packages/vitest/src/runtime/workers/base.ts:146

  const { ctx } = state
  state.environment = _currentEnvironment
  state.durations.environment = _environmentTime
  // state has new context, but we want to reuse existing ones
  state.evaluatedModules = evaluatedModules
  state.moduleExecutionInfo = moduleExecutionInfo

  provideWorkerState(globalThis, state)

  // we could load @vite/env, but it would take ~8ms, while this takes ~0,02ms
  if (state.config.serializedDefines) {
    try {
      runInThisContext(`(() =>{\n${state.config.serializedDefines}})()`, {
        lineOffset: 1,
        filename: 'virtual:load-defines.js',
      })
    }
    catch (error: any) {
      throw new Error(`Failed to load custom "defines": ${error.message}`)
    }
  }

  if (ctx.invalidates) {
    ctx.invalidates.forEach((filepath) => {
      const modules = state.evaluatedModules.fileToModulesMap.get(filepath) || []
      modules.forEach((module) => {
        state.evaluatedModules.invalidateModule(module)
      })
    })
  }
  ctx.files.forEach((i) => {
    const filepath = i.filepath
    const modules = state.evaluatedModules.fileToModulesMap.get(filepath) || []
    modules.forEach((module) => {
      state.evaluatedModules.invalidateModule(module)
    })
  })

View on GitHub (pinned to 1fa9837ec2)