{"record":{"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":139,"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":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/colinhacks/zod/blob/2d90846af918af9602e088812d63a035d47cdbe4/packages/zod/src/v4/classic/from-json-schema.ts#L121-L157","documentation":"Thrown by resolveRef (packages/zod/src/v4/classic/from-json-schema.ts:139) when a local $ref correctly points into $defs/definitions (path[0] === defsKey) but the named key does not exist or is empty. The converter walks the path, finds the defs bucket for the detected draft, looks up the key in ctx.defs, and rejects when the lookup misses — meaning the document references a definition it never declared.","triggerScenarios":"Calling fromJSONSchema with a schema like `{ \"$ref\": \"#/$defs/Missing\" }` or `{ \"$ref\": \"#/definitions/Missing\" }` where 'Missing' is not present in the corresponding $defs/definitions object. Also triggered when the $defs key is misspelled or uses the wrong draft's bucket name for the detected version.","commonSituations":"Renaming a definition without updating its references; truncating a schema document so $defs is dropped; mixing draft-7 'definitions' refs into a draft-2020-12 document (or vice-versa) so the defsKey lookup fails; typos in the definition name; copy-paste of refs from another schema.","solutions":["Check that every name referenced by #/$defs/Name (or #/definitions/Name) exists in the document's $defs/definitions object.","Confirm the document's $schema matches the bucket name used by refs: draft-2020-12 uses $defs, draft-7 uses definitions — the converter picks the bucket based on $schema.","Run the document through a JSON Schema validator/IDE to flag dangling references before conversion.","Add the missing definition or rewrite the ref to point at an existing one."],"exampleFix":"// before\nconst schema = {\n  $schema: 'https://json-schema.org/draft/2020-12/schema',\n  $ref: '#/$defs/User',\n  $defs: { Account: { type: 'object' } }, // 'User' missing\n};\n\n// after\nconst schema = {\n  $schema: 'https://json-schema.org/draft/2020-12/schema',\n  $ref: '#/$defs/User',\n  $defs: { User: { type: 'object', properties: { id: { type: 'string' } } } },\n};","handlingStrategy":"validation","validationCode":"function collectDefinedNames(root: any, version: 'draft-2020-12' | 'draft-7'): Set<string> {\n  const defsKey = version === 'draft-2020-12' ? '$defs' : 'definitions';\n  return new Set(Object.keys(root?.[defsKey] ?? {}));\n}\n\nfunction assertRefsResolve(root: any, version: 'draft-2020-12' | 'draft-7') {\n  const names = collectDefinedNames(root, version);\n  const defsKey = version === 'draft-2020-12' ? '$defs' : 'definitions';\n  const dangling: string[] = [];\n  const visit = (node: unknown) => {\n    if (Array.isArray(node)) return node.forEach(visit);\n    if (!node || typeof node !== 'object') return;\n    const o = node as Record<string, unknown>;\n    if (typeof o.$ref === 'string' && o.$ref.startsWith(`#/${defsKey}/`)) {\n      const name = o.$ref.split('/')[2];\n      if (!names.has(name!)) dangling.push(o.$ref);\n    }\n    for (const v of Object.values(o)) visit(v);\n  };\n  visit(root);\n  if (dangling.length) throw new Error(`Dangling refs: ${dangling.join(', ')}`);\n}","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Confirm every #/$defs/Name (or #/definitions/Name) reference has a matching entry in the document's definitions bucket.","Match the refs' bucket name to the document's declared $schema ($defs for 2020-12, definitions for draft-7).","Validate the source document with a JSON Schema linter before conversion.","When renaming a definition, update all references to it in the same change."],"tags":["json-schema","ref","from-json-schema","conversion","missing-definition"],"backgroundTag":null,"analyzedSha":"2d90846af918af9602e088812d63a035d47cdbe4","analyzedAt":"2026-08-11T01:21:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}