{"id":"fe7ad0e15e4074e4","repo":"vitest-dev/vitest","slug":"bench-expects-a-benchmark-function-call-benc","errorCode":null,"errorMessage":"`bench()` expects a benchmark function. Call `bench(name, fn)` or `bench(name, options, fn)`.","messagePattern":"`bench\\(\\)` expects a benchmark function\\. Call `bench\\(name, fn\\)` or `bench\\(name, options, fn\\)`\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/runtime/benchmark.ts","lineNumber":579,"sourceCode":"function formatModuleId(moduleId: string, root: string): string {\n  if (!root || !isAbsolute(moduleId)) {\n    return moduleId\n  }\n  return relative(root, moduleId)\n}\n\nfunction normalizeBenchArgs(\n  a: BenchFn | BenchFnOptions,\n  b: BenchFn | BenchFnOptions | undefined,\n): { fn: BenchFn; fnOpts: BenchOptions | undefined; writeResult: string | undefined; perProject: boolean } {\n  if (typeof a === 'function') {\n    if (b !== undefined) {\n      throw new TypeError('`bench()` does not accept options as the third argument. Pass options as the second argument instead: `bench(name, options, fn)`.')\n    }\n    return { fn: a, fnOpts: undefined, writeResult: undefined, perProject: false }\n  }\n  if (typeof b !== 'function') {\n    throw new TypeError('`bench()` expects a benchmark function. Call `bench(name, fn)` or `bench(name, options, fn)`.')\n  }\n  // Strip vitest-specific fields only when present so we don't allocate a new\n  // object — preserving referential identity matters: users inspect\n  // `registration.fnOpts` and the provider sees the same object the caller\n  // passed in.\n  if (a.writeResult === undefined && a.perProject === undefined) {\n    return { fn: b, fnOpts: a as BenchOptions, writeResult: undefined, perProject: false }\n  }\n  const { writeResult, perProject, ...fnOpts } = a\n  return {\n    fn: b,\n    fnOpts: Object.keys(fnOpts).length > 0 ? fnOpts as BenchOptions : undefined,\n    writeResult,\n    perProject: perProject ?? false,\n  }\n}\n\nfunction validateBenchmarkProject(config: SerializedConfig) {","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/runtime/benchmark.ts#L561-L597","documentation":"When the second argument to `bench()` is a non-function (treated as `options`), the third argument MUST be the benchmark function. `normalizeBenchArgs` (see `benchmark.ts:579`) throws this `TypeError` when slot 3 is missing or not a function — i.e. `bench(name, options)` with no `fn`, or with a non-function third arg.","triggerScenarios":"`bench('x', { iterations: 10 })` (no fn); `bench('x', opts, 'notafn')`; `bench('x', opts, anotherOptionsObject)`.","commonSituations":"Forgetting the function when adding options; passing options in both slots; refactor that dropped the fn.","solutions":["Add the function as the third argument: `bench('x', { iterations: 10 }, () => thing())`.","If you have no options, use the two-arg form: `bench('x', () => thing())`.","Double-check that slot 2 is options (object) and slot 3 is a function."],"exampleFix":"// before\nbench('sort', { iterations: 100 })\n\n// after\nbench('sort', { iterations: 100 }, () => sortArr())","handlingStrategy":"type-guard","validationCode":"function benchWithOptions(name: string, options: BenchOptions, fn: unknown) {\n  if (typeof fn !== 'function') {\n    throw new TypeError('Third argument to bench(name, options, fn) must be a function')\n  }\n  return bench(name, options, fn)\n}","typeGuard":"function isBenchFn(v: unknown): v is (...args: any[]) => any {\n  return typeof v === 'function'\n}","tryCatchPattern":"try {\n  bench(name, options, fn)\n} catch (e) {\n  if (e instanceof TypeError && /expects a benchmark function/.test(e.message)) {\n    // supply the missing function argument\n  } else throw e\n}","preventionTips":["When passing options, always pass the function as the third argument.","If you have no options, use the two-arg bench(name, fn) form.","Let TypeScript's overload signatures guide you — don't suppress them with any."],"tags":["benchmark","bench","api-misuse","missing-argument","typeerror"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}