vitest-dev/vitest · error · AroundHookSetupError
The `${callbackName}` callback was not called in the `${hook
Error message
The `${callbackName}` callback was not called in the `${hookName}` hook. Make sure to call `${callbackName}` to run the ${hookName === 'aroundEach' ? 'test' : 'suite'}. What it means
If an `aroundEach`/`aroundAll` hook function returns/resolves without ever calling the provided `runTest`/`runSuite` callback, `callAroundHooks` detects that `useCalled` is still false after the hook completes and throws an `AroundHookSetupError` (run.ts:385-390). The hook must invoke the callback so the inner tests/suite actually run.
Source
Thrown at packages/vitest/src/runtime/runner/run.ts:386
// Start teardown timer after inner hooks complete - only times this hook's teardown code
teardownTimeout = createTimeoutPromise(timeout, 'teardown', stackTraceError)
// Signal that use() is returning (teardown phase starting)
resolveUseReturned()
}
setupLimitConcurrencyRelease = await limitMaxConcurrency.acquire()
// Start setup timeout
setupTimeout = createTimeoutPromise(timeout, 'setup', stackTraceError)
// Run the hook in the background
;(async () => {
try {
await invokeHook(hook, use)
if (!useCalled) {
throw new AroundHookSetupError(
`The \`${callbackName}\` callback was not called in the \`${hookName}\` hook. `
+ `Make sure to call \`${callbackName}\` to run the ${hookName === 'aroundEach' ? 'test' : 'suite'}.`,
)
}
resolveHookComplete()
}
catch (error) {
rejectHookComplete(error as Error)
}
finally {
setupLimitConcurrencyRelease?.()
teardownLimitConcurrencyRelease?.()
}
})()
// Wait for either: use() to be called OR hook to complete (error) OR setup timeout
try {
await Promise.race([View on GitHub (pinned to d568f8ce37)
Solutions
- Ensure every code path in the around hook calls `runTest`/`runSuite` exactly once.
- Place the callback call on the unconditional main path, before teardown.
- If the hook should skip the test/suite, use skip mechanisms instead of omitting the call.
Example fix
// before
aroundEach(async (runTest) => {
await setup()
// forgot to call runTest()
})
// after
aroundEach(async (runTest) => {
await setup()
await runTest()
await teardown()
}) Defensive patterns
Strategy: validation
Validate before calling
// Static reminder: every aroundEach/aroundAll must contain a runTest()/runSuite() call. // Use a lint rule requiring the callback name to appear at least once in the hook body.
Prevention
- Always call runTest/runSuite exactly once on the main path.
- Avoid early returns before the callback.
- If skipping, use ctx.skip() or test.skip instead of omitting the call.
When it happens
Trigger: An `aroundEach` hook that forgets to call `runTest()`; an `aroundAll` hook that returns early before `runSuite()`; an awaited condition that throws/swallows before reaching the callback call.
Common situations: Forgetting the callback after refactoring; conditional logic that skips the call on some path; early return/throw that bypasses runTest.
Related errors
- The `${callbackName}` callback was called multiple times in
- Hook ${name}() can only be called inside a test
- Cannot call "onTestFailed" inside a test hook.
- Cannot call "onTestFinished" inside a test hook.
- Page "${sessionId}" not found in ${this.browserName} browser
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/637c23b25bb37162.json.
Report an issue: GitHub.