vitest-dev/vitest · error · Error

Cannot provide " " because it's not serializable.

Error message

Cannot provide "${key}" because it's not serializable.

What it means

project.provide() stores a value in the provided context that is shipped to workers via structured clone (the RPC boundary). Before storing it, Vitest calls structuredClone(value) to fail fast: if the value cannot be cloned (functions, DOM nodes, class instances with non-cloneable internals), it rejects with the offending key named and the clone error as cause.

Solutions

  1. Provide only plain JSON-serializable data (primitives, plain objects, arrays, Date, Map, Set, ArrayBuffer).
  2. If you must pass behavior, provide a serializable token/factory string and reconstruct it inside the test.
  3. Pre-test the value with structuredClone(value) locally to find the non-cloneable member.
  4. Strip functions/proxies/class instances before calling provide.

Example fix

// before
project.provide('db', databaseConnection) // not serializable
// after
project.provide('dbConfig', { url: process.env.DB_URL })
// then connect inside the test using inject('dbConfig')
Defensive patterns

Strategy: validation

Validate before calling

// Mirror Vitest's own check before calling provide.
function safeProvide(project: { provide: (k: string, v: unknown) => void }, key: string, value: unknown) {
  try {
  structuredClone(value)
  } catch (err) {
  throw new Error(`Refusing to provide "${key}": value is not structured-cloneable`, { cause: err })
  }
  project.provide(key as any, value as any)
}

Type guard

const isSerializable = (value: unknown): boolean => {
  try { structuredClone(value); return true } catch { return false }
}

Prevention

When it happens

Trigger: Calling project.provide('key', value) (or the global provide) with a value that fails structuredClone - e.g. a function, a class instance, a Proxy, or an object containing non-transferable members.

Common situations: Providing a function or class instance expecting it to survive the worker boundary, providing a handle to a server/db connection, or providing an object that transitively holds a function.

Related errors


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

Appendix: source

Thrown at packages/vitest/src/node/project.ts:132

          this._fetcher,
          this.config,
        )
  }

  // "provide" is a property, not a method to keep the context when destructed in the global setup,
  // making it a method would be a breaking change, and can be done in Vitest 3 at minimum
  /**
   * Provide a value to the test context. This value will be available to all tests with `inject`.
   */
  provide = <T extends keyof ProvidedContext & string>(
    key: T,
    value: ProvidedContext[T],
  ): void => {
    try {
      structuredClone(value)
    }
    catch (err) {
      throw new Error(
        `Cannot provide "${key}" because it's not serializable.`,
        {
          cause: err,
        },
      )
    }
    // casting `any` because the default type is `never` since `ProvidedContext` is empty
    (this._provided as any)[key] = value
  }

  /**
   * Get the provided context. The project context is merged with the global context.
   */
  getProvidedContext(): ProvidedContext {
    if (this.isRootProject()) {
      return this._provided
    }
    // globalSetup can run even if core workspace is not part of the test run

View on GitHub (pinned to 1fa9837ec2)