{"record":{"id":"8bfec209d43e12de","repo":"vitest-dev/vitest","slug":"custom-reporter-loaded-from-path-was-not-the-de","errorCode":null,"errorMessage":"Custom reporter loaded from ${path} was not the default export","messagePattern":"Custom reporter loaded from (.+?) was not the default export","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/reporters/utils.ts","lineNumber":30,"sourceCode":"): Promise<new (options?: unknown) => C> {\n  let customReporterModule: { default: new () => C }\n  try {\n    customReporterModule = await runner.import(path)\n  }\n  catch (customReporterModuleError) {\n    throw new Error(`Failed to load custom Reporter from ${path}`, {\n      cause: customReporterModuleError as Error,\n    })\n  }\n\n  if (\n    customReporterModule.default === null\n    || customReporterModule.default === undefined\n  ) {\n    throw new Error(\n      `Custom reporter loaded from ${path} was not the default export`,\n    )\n  }\n\n  return customReporterModule.default\n}\n\nfunction createReporters(\n  reporterReferences: ResolvedConfig['reporters'],\n  ctx: Vitest,\n): Promise<Array<Reporter | DefaultReporter | BlobReporter | DotReporter | JsonReporter | TapReporter | JUnitReporter | HangingProcessReporter | GithubActionsReporter>> {\n  const runner = ctx.runner\n  const promisedReporters = reporterReferences.map(\n    async (referenceOrInstance) => {\n      if (Array.isArray(referenceOrInstance)) {\n        const [reporterName, reporterOptions] = referenceOrInstance\n\n        if (reporterName === 'html') {\n          await ctx.packageInstaller.ensureInstalled('@vitest/ui', ctx.config.root, ctx.version)\n          const CustomReporter = await loadCustomReporterModule(\n            '@vitest/ui/reporter',","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/node/reporters/utils.ts#L12-L48","documentation":"The custom reporter module imported successfully but has no `default` export. Vitest's loader (`loadCustomReporterModule`) specifically reads `module.default` as the reporter constructor; a named-only export is rejected.","triggerScenarios":"A reporter file using `export class MyReporter {...}` or `export const MyReporter = ...` with no `export default`; the loader sees `default === null/undefined` after a successful import.","commonSituations":"Converting a CommonJS reporter (`module.exports = MyReporter`) to ESM and forgetting to add a default export; copying a named-export utility as a reporter.","solutions":["Add `export default MyReporter` at the bottom of the reporter module.","Ensure the default export is the reporter class/constructor (Vitest calls `new CustomReporter(options)`)."],"exampleFix":"// before\nexport class MyReporter {\n  onInit(ctx) {}\n  onTestRunEnd() { /* ... */ }\n}\n\n// after\nexport class MyReporter {\n  onInit(ctx) {}\n  onTestRunEnd() { /* ... */ }\n}\nexport default MyReporter","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"import { pathToFileURL } from 'node:url'\n\nasync function isDefaultExportedReporter(path: string): Promise<boolean> {\n  const mod = await import(pathToFileURL(resolve(process.cwd(), path)).href)\n  return typeof mod.default === 'function'\n}","tryCatchPattern":null,"preventionTips":["Always author reporter modules with `export default class MyReporter implements Reporter { ... }`.","When migrating from CommonJS, translate `module.exports = X` to `export default X`."],"tags":["reporter","config","esm"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}