{"record":{"id":"2bb8a6f3802fb704","repo":"vitest-dev/vitest","slug":"bench-compare-requires-at-least-2-benchmarks","errorCode":null,"errorMessage":"`bench.compare()` requires at least 2 benchmarks, received ${registrations.length} instead. ${registrations.length === 1 ? 'Consider calling `bench().run()`. ' : 'Define benchmarks by calling `bench()`. '}See https://vitest.dev/guide/benchmarking#comparing-benchmarks","messagePattern":"`bench\\.compare\\(\\)` requires at least 2 benchmarks, received (.+?) instead\\. (.+?)See https://vitest\\.dev/guide/benchmarking#comparing-benchmarks","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/runtime/benchmark.ts","lineNumber":475,"sourceCode":"    validateBenchmarkProject(config)\n\n    // extract optional trailing BenchRunOptions argument\n    const lastArg = args.at(-1)\n    const isOptions = lastArg != null && typeof lastArg === 'object' && !(kRegistration in lastArg)\n    const benchOptions = isOptions ? args.pop() as BenchRunOptions : undefined\n    const registrations = args as BenchRegistration<any>[]\n\n    // Mark every passed-in registration as consumed before validation so a\n    // throwing `bench.compare()` (wrong arity, wrong shape) doesn't also\n    // trigger the unrun-bench warning — the user's intent was to consume them.\n    for (const reg of registrations) {\n      if (reg != null && typeof reg === 'object' && kRegistration in reg) {\n        pending.delete(reg)\n      }\n    }\n\n    if (registrations.length < 2) {\n      throw new SyntaxError(`\\`bench.compare()\\` requires at least 2 benchmarks, received ${registrations.length} instead. ${registrations.length === 1 ? 'Consider calling `bench().run()`. ' : 'Define benchmarks by calling `bench()`. '}See https://vitest.dev/guide/benchmarking#comparing-benchmarks`)\n    }\n    for (const reg of registrations) {\n      if (reg == null || typeof reg !== 'object' || !(kRegistration in reg)) {\n        throw new SyntaxError('`bench.compare()` expects every argument to be the return value of `bench` or `bench.from`.')\n      }\n    }\n\n    const runnable: RunnableRegistration<any>[] = []\n    const fromEntries: FromRegistration<any>[] = []\n    for (const reg of registrations) {\n      if (isFromRegistration(reg)) {\n        fromEntries.push(reg)\n      }\n      else {\n        runnable.push(reg as RunnableRegistration<any>)\n      }\n    }\n","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/runtime/benchmark.ts#L457-L493","documentation":"`bench.compare(...)` requires at least two benchmark registrations — comparison is meaningless with fewer. This `SyntaxError` fires when zero or one registrations are passed (after stripping a trailing options object). The error message dynamically hints: with 1 registration it suggests `bench().run()`; with 0 it suggests defining benchmarks via `bench()`.","triggerScenarios":"Calling `bench.compare(singleReg)` (1 arg), `bench.compare()` (0 args), or `bench.compare(singleReg, optionsObj)` where the trailing object is detected as `BenchRunOptions` and stripped, leaving one registration. Detection at benchmark.ts:460-462 pops the last arg when it is an object without the `kRegistration` symbol.","commonSituations":"Forgetting to register a second baseline; passing the options object as the only non-registration argument; conditionally building the args array and ending with one element; refactoring `bench().run()` into `bench.compare()` without adding a second benchmark.","solutions":["Pass at least two registrations: `await bench.compare(regA, regB)`.","If you have a single benchmark, call `await reg.run()` or `await bench('name', fn).run()` instead of `bench.compare`.","If passing run options, ensure they are the LAST argument and at least two registrations precede them: `bench.compare(regA, regB, { iterations: 100 })`."],"exampleFix":"// before\nconst a = bench('sort', sortFn)\nawait bench.compare(a) // only one\n\n// after\nawait a.run() // single benchmark\n// or\nconst b = bench('sort2', sort2Fn)\nawait bench.compare(a, b)","handlingStrategy":"validation","validationCode":"if (registrations.length < 2) throw new Error(`need >=2 registrations, got ${registrations.length}`)","typeGuard":"function hasMinTwo<T>(arr: T[]): arr is [T, T, ...T[]] { return arr.length >= 2 }","tryCatchPattern":"null","preventionTips":["Use `bench().run()` for single benchmarks instead of `bench.compare`.","When building args dynamically, assert `regs.length >= 2` before calling.","Place trailing run options only after at least two registrations."],"tags":["benchmark","compare","validation","arity"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}