{"record":{"id":"8dd63f098df194cb","repo":"vitest-dev/vitest","slug":"invalid-diff-config-file-config-diff-must-have","errorCode":null,"errorMessage":"invalid diff config file ${config.diff}. Must have a default export with config object","messagePattern":"invalid diff config file (.+?)\\. Must have a default export with config object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/runtime/setup-common.ts","lineNumber":58,"sourceCode":"): Promise<SerializedDiffOptions | undefined> {\n  if (typeof config.diff === 'object') {\n    return config.diff\n  }\n  if (typeof config.diff !== 'string') {\n    return\n  }\n\n  const diffModule = await moduleRunner.import(config.diff)\n\n  if (\n    diffModule\n    && typeof diffModule.default === 'object'\n    && diffModule.default != null\n  ) {\n    return diffModule.default as DiffOptions\n  }\n  else {\n    throw new Error(\n      `invalid diff config file ${config.diff}. Must have a default export with config object`,\n    )\n  }\n}\n\nexport async function loadSnapshotSerializers(\n  config: SerializedConfig,\n  moduleRunner: PublicModuleRunner,\n): Promise<void> {\n  const files = config.snapshotSerializers\n\n  const snapshotSerializers = await Promise.all(\n    files.map(async (file) => {\n      const mo = await moduleRunner.import(file)\n      if (!mo || typeof mo.default !== 'object' || mo.default === null) {\n        throw new Error(\n          `invalid snapshot serializer file ${file}. Must export a default object`,\n        )","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/runtime/setup-common.ts#L40-L76","documentation":"Thrown by loadDiffConfig when `config.diff` is a string (a file path) but the imported module's default export is not a non-null object. The diff config customizes how assertion diffs are rendered; when provided as a file path it must default-export a DiffOptions object.","triggerScenarios":"Setting `diff: './diff-config.ts'` in vitest config where that file has no default export, exports a primitive/function as default, or exports the config as a named export only.","commonSituations":"Authoring a diff config and forgetting `export default`; exporting a function instead of an object; typo in the file path; using a named export by habit.","solutions":["Default-export a DiffOptions object: `export default { aColor: undefined, bColor: undefined }` (or your chosen keys).","If you only need static options, set `diff` to an object directly in vitest config instead of a file path (loadDiffConfig returns object configs as-is).","Verify the path in `config.diff` resolves to the intended file.","Remove the `diff` option entirely to use defaults."],"exampleFix":"// before — diff-config.ts\nexport const diff = { aAnnotation: 'expected' }\n\n// after\nexport default { aAnnotation: 'expected' }","handlingStrategy":"type-guard","validationCode":"async function loadDiff(path: string) {\n  const mod = await import(/* @vite-ignore */ path)\n  if (!mod?.default || typeof mod.default !== 'object') {\n    throw new TypeError(`${path} must default-export a DiffOptions object`)\n  }\n  return mod.default\n}","typeGuard":"function isDiffOptions(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null\n}","tryCatchPattern":null,"preventionTips":["Prefer passing `diff` as an inline object in config when options are static.","Use `export default { ... }` and nothing else in a diff config file.","Keep diff config files minimal and dedicated (no side effects)."],"tags":["config","diff","validation","esm"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}