{"id":"a48571de734c3f65","repo":"vitest-dev/vitest","slug":"invalid-snapshot-serializer-file-file-must-exp","errorCode":null,"errorMessage":"invalid snapshot serializer file ${file}. Must export a default object","messagePattern":"invalid snapshot serializer file (.+?)\\. Must export a default object","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/runtime/setup-common.ts","lineNumber":74,"sourceCode":"  }\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        )\n      }\n\n      const config = mo.default\n      if (\n        typeof config.test !== 'function'\n        || (typeof config.serialize !== 'function'\n          && typeof config.print !== 'function')\n      ) {\n        throw new TypeError(\n          `invalid snapshot serializer in ${file}. Must have a 'test' method along with either a 'serialize' or 'print' method.`,\n        )\n      }\n\n      return config as SnapshotSerializer\n    }),\n  )","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/runtime/setup-common.ts#L56-L92","documentation":"Thrown by loadSnapshotSerializers when a file listed in `config.snapshotSerializers` does not have a default export that is a non-null object. Each serializer file must `export default { test, serialize/print }`. The default export is the serializer object Vitest registers via @vitest/snapshot's addSerializer.","triggerScenarios":"Listing a path under `test.snapshotSerializers: ['./my-serializer.js']` where the file has no default export, exports default as null, or exports default as a primitive/function. Importing a serializer that uses the older named-export convention.","commonSituations":"Porting a Jest-style snapshot serializer that used `module.exports = { ... }` incorrectly, or that used named exports. Forgetting `default` when converting CJS to ESM. Pointing at a util file that exports helper functions, not a serializer.","solutions":["Use `export default { test, serialize }` in the serializer file.","Confirm the path in `config.snapshotSerializers` resolves to the serializer file.","Drop the file from snapshotSerializers if it was added by mistake.","Migrate named-export serializers to default exports."],"exampleFix":"// before (./my-serializer.js)\nexport const test = () => {}\nexport const serialize = () => {}\n\n// after\nexport default {\n  test: val => typeof val === 'MyType',\n  serialize: (val, config, indent, depth, refs) => `MyType(${val.value})`,\n}","handlingStrategy":"type-guard","validationCode":"import * as mod from './my-serializer.js'\nif (!mod.default || typeof mod.default !== 'object') {\n  throw new Error('serializer must `export default { test, serialize|print }`')\n}","typeGuard":"function isSerializerFile(m: any): m is { default: object } {\n  return Boolean(m && m.default && typeof m.default === 'object')\n}","tryCatchPattern":null,"preventionTips":["Standardize on `export default { test, serialize }`.","Write a tiny test that imports each serializer and asserts its shape.","Do not mix named-export Jest serializers without a default-export wrapper."],"tags":["config","snapshot","serializer","esm"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}