vitest-dev/vitest · error · TypeError

Signature "test(name, fn, { ... })" was deprecated in Vitest

Error message

Signature "test(name, fn, { ... })" was deprecated in Vitest 3 and removed in Vitest 4. Please, provide options as a second argument instead.

What it means

In `parseArguments` (suite.ts:266-302), if the third positional argument to `test`/`it`/`suite` is an object (i.e. the old `test(name, fn, { options })` signature), a `TypeError` is thrown. Vitest 3 deprecated and Vitest 4 removed this signature — options must now be the second argument: `test(name, { options }, fn)`.

Source

Thrown at packages/vitest/src/runtime/runner/suite.ts:271

export function createSuiteHooks(): SuiteHooks {
  return {
    beforeAll: [],
    afterAll: [],
    beforeEach: [],
    afterEach: [],
    aroundEach: [],
    aroundAll: [],
  }
}

const POSITIVE_INFINITY = Number.POSITIVE_INFINITY

function parseArguments<T extends (...args: any[]) => any>(
  optionsOrFn: T | object | undefined,
  timeoutOrTest: T | number | undefined,
) {
  if (timeoutOrTest != null && typeof timeoutOrTest === 'object') {
    throw new TypeError(`Signature "test(name, fn, { ... })" was deprecated in Vitest 3 and removed in Vitest 4. Please, provide options as a second argument instead.`)
  }

  let options: TestOptions = {}
  let fn: T | undefined

  // it('', () => {}, 1000)
  if (typeof timeoutOrTest === 'number') {
    options = { timeout: timeoutOrTest }
  }
  // it('', { retry: 2 }, () => {})
  else if (typeof optionsOrFn === 'object') {
    options = optionsOrFn
  }

  if (typeof optionsOrFn === 'function') {
    if (typeof timeoutOrTest === 'function') {
      throw new TypeError(
        'Cannot use two functions as arguments. Please use the second argument for options.',

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Swap the arguments: put options as the second argument and the function third — `test('name', { retry: 2 }, () => {})`.
  2. Use the codemod/migration guide if upgrading a large suite.
  3. Optionally use a timeout as third arg (a number is still allowed): `test('name', () => {}, 1000)`.

Example fix

// before (Vitest 3, removed in 4)
test('adds', () => { expect(1+1).toBe(2) }, { retry: 2 })
// after (Vitest 4)
test('adds', { retry: 2 }, () => { expect(1+1).toBe(2) })
Defensive patterns

Strategy: validation

Validate before calling

// Detect the removed signature statically.
function isRemovedSignature(args: unknown[]): boolean {
  return typeof args[1] === 'function' && typeof args[2] === 'object' && args[2] !== null && !Array.isArray(args[2])
}
// Lint: ban test(name, fn, {...}) — require options as 2nd arg.

Prevention

When it happens

Trigger: Calling `test('name', () => {}, { retry: 2 })` — function second, options object third; any Vitest 3-or-earlier style three-arg call with an options object in the third slot after upgrading to Vitest 4.

Common situations: Upgrading from Vitest 2/3 to Vitest 4 without migrating test signatures; copying old test patterns from tutorials/docs.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/435aa1fcb9777218.json. Report an issue: GitHub.