{"id":"da72081f692c3ed2","repo":"colinhacks/zod","slug":"duplicate-schema-id-id-detected-during-json-s","errorCode":null,"errorMessage":"Duplicate schema id \"${id}\" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.","messagePattern":"Duplicate schema id \"(.+?)\" detected during JSON Schema conversion\\. Two different schemas cannot share the same id when converted together\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/to-json-schema.ts","lineNumber":234,"sourceCode":"\nexport function extractDefs<T extends schemas.$ZodType>(\n  ctx: ToJSONSchemaContext,\n  schema: T\n  // params: EmitParams\n): void {\n  // iterate over seen map;\n  const root = ctx.seen.get(schema);\n\n  if (!root) throw new Error(\"Unprocessed schema. This is a bug in Zod.\");\n\n  // Track ids to detect duplicates across different schemas\n  const idToSchema = new Map<string, schemas.$ZodType>();\n  for (const entry of ctx.seen.entries()) {\n    const id = ctx.metadataRegistry.get(entry[0])?.id;\n    if (id) {\n      const existing = idToSchema.get(id);\n      if (existing && existing !== entry[0]) {\n        throw new Error(\n          `Duplicate schema id \"${id}\" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`\n        );\n      }\n      idToSchema.set(id, entry[0]);\n    }\n  }\n\n  // returns a ref to the schema\n  // defId will be empty if the ref points to an external schema (or #)\n  const makeURI = (entry: [schemas.$ZodType<unknown, unknown>, Seen]): { ref: string; defId?: string } => {\n    // comparing the seen objects because sometimes\n    // multiple schemas map to the same seen object.\n    // e.g. lazy\n\n    // external is configured\n    const defsSegment = ctx.target === \"draft-2020-12\" ? \"$defs\" : \"definitions\";\n    if (ctx.external) {\n      const externalId = ctx.external.registry.get(entry[0])?.id; // ?? \"__shared\";// `__schema${ctx.counter++}`;","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/colinhacks/zod/blob/912f0f51b0ced654d0069741e7160834dca742ee/packages/zod/src/v4/core/to-json-schema.ts#L216-L252","documentation":"Thrown in `extractDefs` during JSON-Schema conversion. Zod scans every schema it has seen and collects their `.meta({ id })` values; if two distinct schema objects share the same `id`, conversion aborts because the `$defs`/`definitions` keys would collide and `$ref`s would be ambiguous. Ids must be unique across all schemas converted together.","triggerScenarios":"Registering two different schemas with the same id, e.g. `A.meta({ id: 'User' })` and `B.meta({ id: 'User' })` where A and B are different objects, then converting a schema that references both (e.g. via intersection, union, or a shared registry).","commonSituations":"Reusing an id constant across modules; copying a schema definition and forgetting to change its id; merging schemas from multiple files that each tag their primary type with the same generic name like `'Item'`.","solutions":["Give each schema a globally unique `id` in its `.meta({ id })` call.","Search the codebase for the duplicate id reported in the message and rename one of them.","If two schemas are genuinely meant to be the same, share a single schema object/reference rather than defining two with the same id."],"exampleFix":"// before\nconst A = z.object({ name: z.string() }).meta({ id: 'User' });\nconst B = z.object({ email: z.string() }).meta({ id: 'User' });\nz.toJSONSchema(z.object({ a: A, b: B })); // throws\n\n// after\nconst A = z.object({ name: z.string() }).meta({ id: 'NamedUser' });\nconst B = z.object({ email: z.string() }).meta({ id: 'EmailUser' });\nz.toJSONSchema(z.object({ a: A, b: B }));","handlingStrategy":"validation","validationCode":"function assertUniqueIds(schemas) {\n  const seen = new Map();\n  for (const s of schemas) {\n    const id = s._zod?.def?.meta?.id ?? (s as any).meta?.id;\n    // id is usually registered via .meta({ id }); check via the registry if available\n    if (id && seen.has(id) && seen.get(id) !== s) throw new Error(`duplicate id \"${id}\"`);\n    if (id) seen.set(id, s);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  z.toJSONSchema(root);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Duplicate schema id')) {\n    // grep the codebase for the reported id and rename one occurrence\n  }\n  throw e;\n}","preventionTips":["Give every schema with .meta({ id }) a globally unique id.","Centralize id constants in one module to avoid accidental reuse.","Share a single schema object across references instead of redefining with the same id."],"tags":["json-schema","conversion","meta","duplicate-id"],"analyzedSha":"912f0f51b0ced654d0069741e7160834dca742ee","analyzedAt":"2026-08-03T17:41:55.908Z","schemaVersion":2}