vitest-dev/vitest · error · Error
Hook () can only be called inside a test
Error message
Hook ${name}() can only be called inside a test What it means
Thrown by createTestHook, the factory behind onTestFailed and onTestFinished. These hooks bind to the currently executing test, so they require a live test context (getCurrentTest() must return a test). Calling them at module top-level, inside describe/setup hooks, or inside beforeAll/afterAll yields no current test and triggers this error.
Solutions
- Move the onTestFailed/onTestFinished call inside the test() callback body.
- For shared logic, accept the context as a parameter and call `context.onTestFinished` from within the test.
- Use beforeEach/afterEach for setup/teardown that applies to every test rather than onTestFinished.
Example fix
// before
beforeEach(() => {
onTestFailed(() => cleanup()) // throws: not in a test
})
// after
test('x', () => {
onTestFailed(() => cleanup())
}) Defensive patterns
Strategy: validation
Validate before calling
import { getCurrentTest } from 'vitest'
function registerAfterTest(fn: () => void) {
if (!getCurrentTest()) throw new Error('onTestFinished must be called inside a test')
onTestFinished(fn)
} Type guard
const inTest = () => !!getCurrentTest()
Prevention
- Only call onTestFailed/onTestFinished from within a test() body.
- Pass the test context into helpers rather than calling globals from hooks.
- Use beforeEach/afterEach for hook-scoped setup/teardown.
When it happens
Trigger: Calling `onTestFailed(fn)` or `onTestFinished(fn)` at the top level of a test file; inside a beforeAll/afterAll/beforeEach/afterEach hook body (those run outside the test execution frame); inside describe factory body before any test runs.
Common situations: Factoring shared cleanup into a helper that calls onTestFinished unconditionally; pasting test-body code into a hook during refactor; calling onTestFailed from a setup utility module.
Related errors
- Cannot call "onTestFailed" inside a test hook.
- Cannot call "onTestFinished" inside a test hook.
- Cannot annotate tests outside of the test run. The test
- expect.soft() can only be used inside a test
- The ` ` callback was called multiple times in the ` ` hook…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/2deacf699ecb7128.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vitest/src/runtime/runner/hooks.ts:454
}
export function getAroundHookStackTrace(hook: Function): Error | undefined {
return AROUND_STACK_TRACE_KEY in hook && hook[AROUND_STACK_TRACE_KEY] instanceof Error
? hook[AROUND_STACK_TRACE_KEY]
: undefined
}
function createTestHook<T>(
name: string,
handler: (test: TaskPopulated, handler: T, timeout?: number) => void,
): TaskHook<T> {
return (fn: T, timeout?: number) => {
assertTypes(fn, `"${name}" callback`, ['function'])
const current = getCurrentTest()
if (!current) {
throw new Error(`Hook ${name}() can only be called inside a test`)
}
return handler(current, fn, timeout)
}
}
View on GitHub (pinned to 1fa9837ec2)