{"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":522,"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":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/colinhacks/zod/blob/912f0f51b0ced654d0069741e7160834dca742ee/packages/zod/src/v4/core/to-json-schema.ts#L504-L540","documentation":"Thrown as a fallback when `JSON.parse(JSON.stringify(result))` fails at the very end of `z.toJSONSchema()`. The conversion produces a result object that cannot be serialized to JSON — typically because an unhandled circular reference remains in the output (a cycle that wasn't extracted to a `$ref`), or because the schema metadata contains non-serializable values like functions, `Date` objects in unexpected places, or `BigInt`.","triggerScenarios":"A recursive schema converted without `cycles: 'ref'` leaving a live cycle in the output; attaching functions, class instances, or `BigInt` to schema metadata that gets spread into the JSON Schema; a custom `toJSONSchema` override returning an object with circular links.","commonSituations":"Custom schemas whose `toJSONSchema`/`processJSONSchema` returns non-serializable content; metadata (`examples`, `default`) holding functions or Dates; uncaught recursion when `cycles` handling didn't fire.","solutions":["If the schema is recursive, convert with `{ cycles: 'ref' }` so cycles become `$ref`s instead of live links.","Inspect `.meta(...)` values (examples, default, custom fields) and ensure they are plain JSON-serializable (strings/numbers/booleans/arrays/plain objects) — remove functions, Dates, BigInts.","If using a custom `toJSONSchema`/`processJSONSchema`, ensure its return value is acyclic and JSON-safe; call `JSON.stringify` on it yourself to debug."],"exampleFix":"// before\nconst S = z.object({ a: z.string() }).meta({\n  examples: [{ a: 'x' }],\n  default: () => ({ a: '' }), // function — not serializable\n});\nz.toJSONSchema(S); // throws\n\n// after\nconst S = z.object({ a: z.string() }).meta({\n  examples: [{ a: 'x' }],\n  default: { a: '' },\n});\nz.toJSONSchema(S);","handlingStrategy":"validation","validationCode":"function isJsonSafe(v, seen = new WeakSet()) {\n  if (v === null || typeof v !== 'object') return typeof v !== 'function' && typeof v !== 'bigint' || typeof v === 'bigint' ? false : true;\n  if (typeof v === 'function') return false;\n  if (seen.has(v)) return false;\n  seen.add(v);\n  for (const k in v) if (!isJsonSafe(v[k], seen)) return false;\n  return true;\n}\n// before converting, sanity-check the produced result manually:\n// JSON.parse(JSON.stringify(z.toJSONSchema(schema, { cycles: 'ref' })))","typeGuard":"function isJsonSafe(v, seen = new WeakSet()): boolean {\n  if (v === null) return true;\n  const t = typeof v;\n  if (t === 'function' || t === 'bigint' || t === 'symbol') return false;\n  if (t !== 'object') return true;\n  if (seen.has(v)) return false;\n  seen.add(v);\n  return Object.values(v).every((x) => isJsonSafe(x, seen));\n}","tryCatchPattern":"try {\n  z.toJSONSchema(schema);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Error converting schema to JSON.') {\n    // retry with cycles:'ref', and strip non-serializable meta (functions, Dates, BigInt)\n    z.toJSONSchema(schema, { cycles: 'ref' });\n  }\n  throw e;\n}","preventionTips":["Convert recursive schemas with cycles:'ref' so cycles become $refs.","Keep .meta() values JSON-serializable (no functions, Dates, BigInt, class instances).","Test toJSONSchema output by round-tripping through JSON.parse(JSON.stringify(...))."],"tags":["json-schema","conversion","serialization","cycles"],"analyzedSha":"912f0f51b0ced654d0069741e7160834dca742ee","analyzedAt":"2026-08-03T17:41:55.908Z","schemaVersion":2}