{"id":"436328b19188ff6f","repo":"colinhacks/zod","slug":"reference-not-found-ref","errorCode":null,"errorMessage":"Reference not found: ${ref}","messagePattern":"Reference not found: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/zod/src/v4/classic/from-json-schema.ts","lineNumber":138,"sourceCode":"\nfunction resolveRef(ref: string, ctx: ConversionContext): JSONSchema.JSONSchema {\n  if (!ref.startsWith(\"#\")) {\n    throw new Error(\"External $ref is not supported, only local refs (#/...) are allowed\");\n  }\n\n  const path = ref.slice(1).split(\"/\").filter(Boolean);\n\n  // Handle root reference \"#\"\n  if (path.length === 0) {\n    return ctx.rootSchema;\n  }\n\n  const defsKey = ctx.version === \"draft-2020-12\" ? \"$defs\" : \"definitions\";\n\n  if (path[0] === defsKey) {\n    const key = path[1];\n    if (!key || !ctx.defs[key]) {\n      throw new Error(`Reference not found: ${ref}`);\n    }\n    return ctx.defs[key]!;\n  }\n\n  throw new Error(`Reference not found: ${ref}`);\n}\n\nfunction convertBaseSchema(schema: JSONSchema.JSONSchema, ctx: ConversionContext): ZodType {\n  // Handle unsupported features\n  if (schema.not !== undefined) {\n    // Special case: { not: {} } represents never\n    if (typeof schema.not === \"object\" && Object.keys(schema.not).length === 0) {\n      return z.never();\n    }\n    throw new Error(\"not is not supported in Zod (except { not: {} } for never)\");\n  }\n  if (schema.unevaluatedItems !== undefined) {\n    throw new Error(\"unevaluatedItems is not supported\");","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/colinhacks/zod/blob/912f0f51b0ced654d0069741e7160834dca742ee/packages/zod/src/v4/classic/from-json-schema.ts#L120-L156","documentation":"Thrown by resolveRef when a `#/...` ref correctly points into `$defs`/`definitions` but the named key is missing (or empty). The converter looked up `ctx.defs[key]` and it was undefined.","triggerScenarios":"A schema with `{ \"$ref\": \"#/$defs/User\" }` but no `$defs.User` entry; renaming a definition without updating its ref; using the wrong defs key for the detected draft version.","commonSituations":"Hand-editing schemas and dropping a definition; copy-paste that changes the path but not the key; mixing draft-7 `definitions` with 2020-12 `$defs` while the converter resolves under one key only.","solutions":["Add the missing definition under `$defs` (or `definitions` for draft-7) with the exact key from the ref.","Verify the defs container name matches the detected draft (`$schema` header); convert to the matching key.","Search the schema for every `$ref` and confirm each target exists in `$defs`/`definitions`."],"exampleFix":"// before\n{ \"$ref\": \"#/$defs/User\" } // no $defs.User present\n\n// after\n{\n  \"$defs\": {\n    \"User\": { \"type\": \"object\", \"properties\": { \"id\": { \"type\": \"string\" } } }\n  },\n  \"$ref\": \"#/$defs/User\"\n}","handlingStrategy":"validation","validationCode":"function assertRefsResolve(schema: any) {\n  const defs = schema.$defs ?? schema.definitions ?? {};\n  const visit = (n: any) => {\n    if (n && typeof n === \"object\") {\n      if (typeof n.$ref === \"string\") {\n        const key = n.$ref.split(\"/\").pop();\n        if (!defs[key]) throw new Error(`Unresolved $ref: ${n.$ref}`);\n      }\n      Object.values(n).forEach(visit);\n    }\n  };\n  visit(schema);\n}","typeGuard":"function defsHasKey(schema: any, ref: string): boolean {\n  const defs = schema.$defs ?? schema.definitions ?? {};\n  const key = ref.split(\"/\").pop();\n  return key != null && key in defs;\n}","tryCatchPattern":null,"preventionTips":["Validate every `$ref` resolves to a `$defs` entry before conversion.","Generate `$defs` from a single source so renaming stays in sync.","Run a ref-resolution lint in CI for bundled schemas."],"tags":["json-schema","ref","v4","from-json-schema"],"analyzedSha":"912f0f51b0ced654d0069741e7160834dca742ee","analyzedAt":"2026-08-03T17:41:55.908Z","schemaVersion":2}