{"record":{"id":"ddb02d47e6ee34a1","repo":"vitest-dev/vitest","slug":"test-runner-doesn-t-support-test-annotations","errorCode":null,"errorMessage":"Test runner doesn't support test annotations.","messagePattern":"Test runner doesn't support test annotations\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/runtime/runner/context.ts","lineNumber":211,"sourceCode":"    }\n\n    const annotation: TestAnnotation = {\n      message,\n      type: typeof type === 'object' || type === undefined ? 'notice' : type,\n    }\n    const annotationAttachment = typeof type === 'object' ? type : attachment\n\n    if (annotationAttachment) {\n      annotation.attachment = annotationAttachment\n\n      manageArtifactAttachment(annotation.attachment)\n    }\n\n    return recordAsyncOperation(\n      test,\n      recordArtifact(test, { type: 'internal:annotation', annotation }).then(async ({ annotation }) => {\n        if (!runner.onTestAnnotate) {\n          throw new Error(`Test runner doesn't support test annotations.`)\n        }\n\n        await finishSendTasksUpdate(runner)\n\n        const resolvedAnnotation = await runner.onTestAnnotate(test, annotation)\n        test.annotations.push(resolvedAnnotation)\n        return resolvedAnnotation\n      }),\n    )\n  }) as TestContext['annotate']\n\n  context.onTestFailed = (handler, timeout) => {\n    test.onFailed ||= []\n    test.onFailed.push(\n      withTimeout(\n        handler,\n        timeout ?? runner.config.hookTimeout,\n        true,","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/runtime/runner/context.ts#L193-L229","documentation":"Thrown from context.annotate when the active VitestRunner has no `onTestAnnotate` method. Annotation support is opt-in for custom runners; the built-in runners implement it, but a hand-rolled VitestRunner subclass may not. The error fires at annotation time, not at runner registration.","triggerScenarios":"Subclassing VitestRunner without overriding onTestAnnotate; using a third-party runner that predates the annotation API; calling ctx.annotate inside a test driven by a minimal custom runner.","commonSituations":"Building a custom runner for a non-standard environment (e.g., embedded, proprietary harness); pinning an old runner version while the test code uses new annotation APIs.","solutions":["Implement `onTestAnnotate(test, annotation)` on your custom VitestRunner subclass.","Switch to the built-in runner (e.g., VitestTestRunner) which supports annotations.","If you cannot change the runner, avoid ctx.annotate and record metadata via expect or custom logging instead."],"exampleFix":"// before\nclass MyRunner extends VitestRunner {\n  // missing onTestAnnotate\n}\n\n// after\nclass MyRunner extends VitestRunner {\n  onTestAnnotate(test, annotation) {\n    test.annotations.push(annotation)\n    return annotation\n  }\n}","handlingStrategy":"type-guard","validationCode":"const runnerSupportsAnnotations = (r: VitestRunner) =>\n  typeof (r as any).onTestAnnotate === 'function'","typeGuard":"function supportsAnnotate(r: VitestRunner): r is VitestRunner & { onTestAnnotate: NonNullable<VitestRunner['onTestAnnotate']> } {\n  return typeof r.onTestAnnotate === 'function'\n}","tryCatchPattern":null,"preventionTips":["Prefer the built-in VitestTestRunner unless you need a custom one.","If subclassing VitestRunner, implement onTestAnnotate to forward annotations.","Feature-detect annotation support before using ctx.annotate in shared libraries."],"tags":["runner","annotations","custom-runner","artifact"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}