{"id":"435aa1fcb9777218","repo":"vitest-dev/vitest","slug":"signature-test-name-fn-was-deprecated","errorCode":null,"errorMessage":"Signature \"test(name, fn, { ... })\" was deprecated in Vitest 3 and removed in Vitest 4. Please, provide options as a second argument instead.","messagePattern":"Signature \"test\\(name, fn, (.+?)\\)\" was deprecated in Vitest 3 and removed in Vitest 4\\. Please, provide options as a second argument instead\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/runtime/runner/suite.ts","lineNumber":271,"sourceCode":"export function createSuiteHooks(): SuiteHooks {\n  return {\n    beforeAll: [],\n    afterAll: [],\n    beforeEach: [],\n    afterEach: [],\n    aroundEach: [],\n    aroundAll: [],\n  }\n}\n\nconst POSITIVE_INFINITY = Number.POSITIVE_INFINITY\n\nfunction parseArguments<T extends (...args: any[]) => any>(\n  optionsOrFn: T | object | undefined,\n  timeoutOrTest: T | number | undefined,\n) {\n  if (timeoutOrTest != null && typeof timeoutOrTest === 'object') {\n    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.`)\n  }\n\n  let options: TestOptions = {}\n  let fn: T | undefined\n\n  // it('', () => {}, 1000)\n  if (typeof timeoutOrTest === 'number') {\n    options = { timeout: timeoutOrTest }\n  }\n  // it('', { retry: 2 }, () => {})\n  else if (typeof optionsOrFn === 'object') {\n    options = optionsOrFn\n  }\n\n  if (typeof optionsOrFn === 'function') {\n    if (typeof timeoutOrTest === 'function') {\n      throw new TypeError(\n        'Cannot use two functions as arguments. Please use the second argument for options.',","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/runtime/runner/suite.ts#L253-L289","documentation":"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)`.","triggerScenarios":"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.","commonSituations":"Upgrading from Vitest 2/3 to Vitest 4 without migrating test signatures; copying old test patterns from tutorials/docs.","solutions":["Swap the arguments: put options as the second argument and the function third — `test('name', { retry: 2 }, () => {})`.","Use the codemod/migration guide if upgrading a large suite.","Optionally use a timeout as third arg (a number is still allowed): `test('name', () => {}, 1000)`."],"exampleFix":"// before (Vitest 3, removed in 4)\ntest('adds', () => { expect(1+1).toBe(2) }, { retry: 2 })\n// after (Vitest 4)\ntest('adds', { retry: 2 }, () => { expect(1+1).toBe(2) })","handlingStrategy":"validation","validationCode":"// Detect the removed signature statically.\nfunction isRemovedSignature(args: unknown[]): boolean {\n  return typeof args[1] === 'function' && typeof args[2] === 'object' && args[2] !== null && !Array.isArray(args[2])\n}\n// Lint: ban test(name, fn, {...}) — require options as 2nd arg.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When upgrading to Vitest 4, search for `test(.*,.*,\\s*{` and swap args.","Adopt the canonical `test(name, options, fn)` form.","Run the Vitest migration codemod if available."],"tags":["deprecation","migration","vitest-4","signature","breaking-change"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}