vitest-dev/vitest · error · Error

Custom reporter loaded from ${path} was not the default expo

Error message

Custom reporter loaded from ${path} was not the default export

What it means

Thrown by `loadCustomReporterModule` (utils.ts:27) when the custom reporter module imports successfully but has no `default` export (`customReporterModule.default` is null/undefined). Vitest requires the reporter constructor to be the default export so it can do `new CustomReporter(options)`; a named-only export or a side-effect-only module is rejected.

Source

Thrown at packages/vitest/src/node/reporters/utils.ts:27

async function loadCustomReporterModule<C extends Reporter>(
  path: string,
  runner: ModuleRunner,
): Promise<new (options?: unknown) => C> {
  let customReporterModule: { default: new () => C }
  try {
    customReporterModule = await runner.import(path)
  }
  catch (customReporterModuleError) {
    throw new Error(`Failed to load custom Reporter from ${path}`, {
      cause: customReporterModuleError as Error,
    })
  }

  if (
    customReporterModule.default === null
    || customReporterModule.default === undefined
  ) {
    throw new Error(
      `Custom reporter loaded from ${path} was not the default export`,
    )
  }

  return customReporterModule.default
}

function createReporters(
  reporterReferences: ResolvedConfig['reporters'],
  ctx: Vitest,
): Promise<Array<Reporter | DefaultReporter | BlobReporter | DotReporter | JsonReporter | TapReporter | JUnitReporter | HangingProcessReporter | GithubActionsReporter>> {
  const runner = ctx.runner
  const promisedReporters = reporterReferences.map(
    async (referenceOrInstance) => {
      if (Array.isArray(referenceOrInstance)) {
        const [reporterName, reporterOptions] = referenceOrInstance

        if (reporterName === 'html') {

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Add `export default` to the reporter class/function in the module.
  2. Confirm the configured path points to the file that actually has the default export.
  3. If loading from a package, check the package's entry exports a default.

Example fix

// before
export class MyReporter implements Reporter { /* ... */ }
// after
export default class MyReporter implements Reporter { /* ... */ }
Defensive patterns

Strategy: validation

Validate before calling

const mod = await import(reporterPath)
if (mod.default == null || typeof mod.default !== 'function') {
  throw new Error(`${reporterPath} must have a default export constructor`)
}

Type guard

const hasDefaultReporter = (m: Record<string, unknown>): m is { default: new (o?: unknown) => any } =>
  typeof m.default === 'function'

Prevention

When it happens

Trigger: Writing a reporter with only a named export (e.g. `export class MyReporter`) and no `export default`; a reporter module whose default export was tree-shaken or is conditionally undefined; importing a utility module instead of the reporter module.

Common situations: Forgetting the `default` keyword when authoring a custom reporter; refactoring that moved the class to a named export; pointing at the wrong entry file of a multi-file reporter package.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/8bfec209d43e12de.json. Report an issue: GitHub.