vitest-dev/vitest · error · Error
Runner must export a default function, but got
Error message
Runner must export a default function, but got ${typeof mod.default} imported from ${config.runner} What it means
Thrown by getTestRunnerConstructor when the module referenced by the config `runner` option is imported successfully but has no usable default-exported constructor function. Vitest instantiates the custom runner via `new mod.default(config)`, so the default export must be a class or function. The message reports the actual typeof the default export for diagnosis.
Solutions
- Add `export default` to the runner class: `export default class MyRunner extends VitestTestRunner { ... }`.
- If the runner is a named export, re-export it as default: `export { MyRunner as default } from './MyRunner'`.
- Verify `config.runner` points to the file that contains the class, not a config or barrel file.
- Ensure the default export is a constructor (class or function), not an instance or plain object.
Example fix
// before — my-runner.ts
export class MyRunner extends VitestTestRunner { ... }
// after
export default class MyRunner extends VitestTestRunner { ... } Defensive patterns
Strategy: type-guard
Validate before calling
import { importMeta } from './loader' // your dynamic import helper
async function loadRunner(path: string) {
const mod = await import(/* @vite-ignore */ path)
if (typeof mod.default !== 'function') {
throw new TypeError(`Custom runner at ${path} must default-export a constructor`)
}
return mod.default
} Type guard
import type { VitestRunnerConstructor } from 'vitest/runners'
function isRunnerCtor(
mod: any,
): mod is VitestRunnerConstructor {
return typeof mod?.default === 'function'
} Prevention
- Always `export default class` when authoring a custom runner.
- In CI, add a smoke test that imports the runner file and asserts typeof default === 'function'.
- Prefer extending VitestTestRunner so the contract is inherited.
When it happens
Trigger: Setting `runner: './my-runner.ts'` in vitest config where that file has no default export, exports a default that is an object/value (not callable), or uses a named export instead of default.
Common situations: Writing a custom runner and forgetting `export default class MyRunner`; exporting the runner as a named export (`export class MyRunner`); default-exporting a configuration object instead of the class; pointing `runner` at the wrong file path.
Related errors
- Runner must implement "importFile" method.
- Custom reporter loaded from
- invalid diff config file
- invalid snapshot serializer file
- Test runner doesn't support test annotations.
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/7960cf0a824dcf1c.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vitest/src/runtime/runners/index.ts:20
import type { SerializedConfig } from '../config'
import type { TestModuleRunner } from '../moduleRunner/testModuleRunner'
import type { VitestRunner, VitestRunnerConstructor } from '../runner/types'
import { takeCoverageInsideWorker } from '../../integrations/coverage'
import { rpc } from '../rpc'
import { loadDiffConfig, loadSnapshotSerializers } from '../setup-common'
import { getWorkerState } from '../utils'
import { TestRunner } from './test'
async function getTestRunnerConstructor(
config: SerializedConfig,
moduleRunner: TestModuleRunner,
): Promise<VitestRunnerConstructor> {
if (!config.runner) {
return TestRunner as any as VitestRunnerConstructor
}
const mod = await moduleRunner.import(config.runner)
if (!mod.default && typeof mod.default !== 'function') {
throw new Error(
`Runner must export a default function, but got ${typeof mod.default} imported from ${
config.runner
}`,
)
}
return mod.default as VitestRunnerConstructor
}
export async function resolveTestRunner(
config: SerializedConfig,
moduleRunner: TestModuleRunner,
traces: Traces,
): Promise<VitestRunner> {
const TestRunner = await getTestRunnerConstructor(config, moduleRunner)
const testRunner = new TestRunner(config)
// inject private executor to every runner
Object.defineProperty(testRunner, 'moduleRunner', {View on GitHub (pinned to 1fa9837ec2)