{"record":{"id":"53c242ee4c5353cc","repo":"colinhacks/zod","slug":"error-converting-schema-to-json","errorCode":null,"errorMessage":"Error converting schema to JSON.","messagePattern":"Error converting schema to JSON\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/core/to-json-schema.ts","lineNumber":523,"sourceCode":"    // this \"finalizes\" this schema and ensures all cycles are removed\n    // each call to finalize() is functionally independent\n    // though the seen map is shared\n    const finalized = JSON.parse(JSON.stringify(result));\n    Object.defineProperty(finalized, \"~standard\", {\n      value: {\n        ...schema[\"~standard\"],\n        jsonSchema: {\n          input: createStandardJSONSchemaMethod(schema, \"input\", ctx.processors),\n          output: createStandardJSONSchemaMethod(schema, \"output\", ctx.processors),\n        },\n      },\n      enumerable: false,\n      writable: false,\n    });\n\n    return finalized;\n  } catch (_err) {\n    throw new Error(\"Error converting schema to JSON.\");\n  }\n}\n\nfunction isTransforming(\n  _schema: schemas.$ZodType,\n  _ctx?: {\n    seen: Set<schemas.$ZodType>;\n  }\n): boolean {\n  const ctx = _ctx ?? { seen: new Set() };\n\n  if (ctx.seen.has(_schema)) return false;\n  ctx.seen.add(_schema);\n\n  const def = (_schema as schemas.$ZodTypes)._zod.def;\n\n  if (def.type === \"transform\") return true;\n","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v4/core/to-json-schema.ts#L505-L541","documentation":"Thrown at the very end of z.toJSONSchema() when JSON.parse(JSON.stringify(result)) throws while finalizing the generated schema. The deep-clone is used to guarantee the output has no cycles and no non-serializable values; any residual circular reference, function/Symbol in the result, or bigint/Date that escaped the processors will cause JSON.stringify to fail, which the catch wraps in a generic message.","triggerScenarios":"A schema that, after processing, yields a result object JSON.stringify cannot serialize — most often a residual circular reference that wasn't converted to $ref (e.g. cycles option mishandled, or a custom processor that reintroduces a cycle), or a custom schema type that injected a function/bigint/Symbol into the JSON Schema output. Also reachable if a metadata override attached a non-serializable value.","commonSituations":"Custom processors or override callbacks that attach non-JSON values; recursive schemas converted without cycles:\"ref\" that slipped past the earlier cycle check (e.g. a cycle introduced during processing rather than in the input graph); .meta() carrying function-valued keys; third-party plugins that mutate the result.","solutions":["Pass { cycles: \"ref\" } to handle recursive schemas via $defs/$ref instead of embedded cycles.","Audit custom override/processor code and .meta() for non-serializable values (functions, Symbols, bigints).","Reproduce locally and inspect `result` just before the clone to locate the offending property.","Strip or stringify metadata values before registering them on schemas."],"exampleFix":"// before — recursive schema without cycles option, or meta with a function\nconst Tree = z.lazy(() => z.object({ kids: z.array(Tree) }));\nconst json = z.toJSONSchema(Tree);\n// after\nconst json = z.toJSONSchema(Tree, { cycles: \"ref\" });","handlingStrategy":"try-catch","validationCode":"function isSerializable(v: unknown): boolean {\n  try { JSON.stringify(v); return true; } catch { return false; }\n}","typeGuard":"function isSerializable(v: unknown): boolean {\n  try { JSON.stringify(v); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  return z.toJSONSchema(schema);\n} catch (e) {\n  if (/Error converting schema to JSON/.test((e as Error).message)) {\n    return z.toJSONSchema(schema, { cycles: \"ref\" });\n  }\n  throw e;\n}","preventionTips":["Always pass { cycles: \"ref\" } for recursive schemas.","Keep .meta() values JSON-serializable (no functions/Symbols/bigints).","Audit custom override/processor callbacks for non-serializable mutations.","Reproduce locally and inspect the pre-clone `result` to find the offending property."],"tags":["json-schema","conversion","serialization","cycle","metadata"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}