vitest-dev/vitest · error · Error
Test function is not found. Did you add it using `setFn`?
Error message
Test function is not found. Did you add it using `setFn`?
What it means
During `runTest` (run.ts:647-652), if the runner has no custom `runTask`, Vitest fetches the test's function via `getFn(test)`. If no function was registered for the task (via `setFn`), it throws this error pointing to `setFn`. This indicates the task was collected without an executable body — typically a setup/registration bug rather than a user test error.
Source
Thrown at packages/vitest/src/runtime/runner/run.ts:649
})
test.result!.repeatCount = repeatCount
beforeEachCleanups = await $('test.beforeEach', () => callSuiteHook(
suite,
test,
'beforeEach',
runner,
[test.context, suite],
))
if (runner.runTask) {
await $('test.callback', () => limitMaxConcurrency(() => runner.runTask!(test)))
}
else {
const fn = getFn(test)
if (!fn) {
throw new Error(
'Test function is not found. Did you add it using `setFn`?',
)
}
await $('test.callback', () => limitMaxConcurrency(() => fn()))
}
await runner.onAfterTryTask?.(test, {
retry: retryCount,
repeats: repeatCount,
})
if (test.result!.state !== 'fail') {
test.result!.state = 'pass'
}
}
catch (e) {
failTask(test.result!, e, runner.config._diffOptions)
}View on GitHub (pinned to d568f8ce37)
Solutions
- Ensure `setFn(task, fn)` is called for every test task before it runs.
- Use the standard `test(...)` API which registers the function automatically.
- If using a custom runner, implement `runner.runTask` or guarantee `setFn` is invoked during collection.
Example fix
// before: custom task without function
const task = createTestTask()
await runTest(task, runner) // getFn returns undefined
// after
setFn(task, () => { /* test body */ })
await runTest(task, runner) Defensive patterns
Strategy: validation
Validate before calling
// Custom runner: ensure setFn is called for every task.
import { setFn } from 'vitest/runtime'
function ensureFn(task: Test) {
if (typeof (task as any).fn !== 'function') {
setFn(task, () => { throw new Error(`No body for ${task.name}`) })
}
} Prevention
- Prefer the standard test()/it() API which registers functions automatically.
- In custom runners, always pair task creation with setFn.
- Implement runner.runTask if you bypass the default getFn path.
When it happens
Trigger: A custom runner or plugin that creates a `Test` task and calls `runTest` without first registering a function via `setFn`; manually constructing tasks; a collection path that skips `setFn` assignment.
Common situations: Custom Vitest runner implementations; programmatic test creation; bugs in test-collection middleware; running a `todo` task that has no body but reached execution.
Related errors
- Vitest Module Runner doesn't support Vite HMR events.
- Cannot find iframe with id ${event.iframeId}
- Failed to import test file ${filepath}
- Cannot spawn child server without a parent dev server.
- [@vitest/mocker] `createMockInstance` is not defined. This i
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/997ee2934cd76e77.json.
Report an issue: GitHub.