{"record":{"id":"1be6a97bd1d7a7f0","repo":"can1357/oh-my-pi","slug":"unresolved-ref-ref","errorCode":null,"errorMessage":"unresolved $ref: ${ref}","messagePattern":"unresolved \\$ref: (.+?)","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/from-json-schema.ts","lineNumber":52,"sourceCode":"\treadonly #aliases = new Map<string, IR>();\n\n\tconstructor(root: JsonSchema) {\n\t\tthis.#root = root;\n\t}\n\n\tresolveRef(ref: string): IR {\n\t\tconst cached = this.#aliases.get(ref);\n\t\tif (cached !== undefined) return cached;\n\n\t\tlet target: unknown;\n\t\tif (ref === \"#\") {\n\t\t\ttarget = this.#root;\n\t\t} else {\n\t\t\tconst defsMatch = /^#\\/(\\$defs|definitions)\\/(.+)$/.exec(ref);\n\t\t\tif (defsMatch === null) throw new OmpTypeError(`unsupported $ref: ${ref}`);\n\t\t\tconst defs = this.#root[defsMatch[1]];\n\t\t\ttarget = typeof defs === \"object\" && defs !== null ? (defs as JsonSchema)[defsMatch[2]] : undefined;\n\t\t\tif (target === undefined) throw new OmpTypeError(`unresolved $ref: ${ref}`);\n\t\t}\n\n\t\t// Register the alias before lowering so recursive references resolve\n\t\t// to the same node instead of recursing forever.\n\t\tlet lowered: IR | undefined;\n\t\tconst alias: IR = {\n\t\t\tk: \"alias\",\n\t\t\tname: ref,\n\t\t\tresolve: () => {\n\t\t\t\tlowered ??= this.lower(target);\n\t\t\t\treturn lowered;\n\t\t\t},\n\t\t};\n\t\tthis.#aliases.set(ref, alias);\n\t\treturn alias;\n\t}\n\n\tlower(schema: unknown): IR {","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/from-json-schema.ts#L34-L70","documentation":"A `$ref` matched the `#/$defs/Name` or `#/definitions/Name` shape, but the named definition does not exist (or the defs container itself is missing/not an object). This is a dangling reference: the schema points at a definition that was never declared.","triggerScenarios":"`{\"$ref\": \"#/$defs/Missing\"}` when `$defs` is empty, omitted, or lacks the key `Missing`; typo in the definition name; def stripped by a bundler/pruner.","commonSituations":"Hand-edited schemas with typos; code-generated schemas referencing defs that were filtered out; case-sensitivity mismatches (`#/$defs/user` vs `User`).","solutions":["Add the missing definition under `$defs` (or `definitions`) with the exact referenced name.","Fix the typo / casing in the `$ref` string to match an existing definition.","Validate the schema with a JSON Schema validator before conversion to catch dangling refs."],"exampleFix":"// before\n{ \"type\": \"object\", \"properties\": { \"id\": { \"$ref\": \"#/$defs/Id\" } } } // no $defs\n// after\n{ \"type\": \"object\", \"properties\": { \"id\": { \"$ref\": \"#/$defs/Id\" } }, \"$defs\": { \"Id\": { \"type\": \"string\" } } }","handlingStrategy":"validation","validationCode":"function refsResolve(schema: Record<string, unknown>): boolean {\n  const defs = (schema.$defs ?? schema.definitions) as Record<string, unknown> | undefined;\n  const walk = (node: unknown): boolean => {\n    if (typeof node !== \"object\" || node === null) return true;\n    const ref = (node as { $ref?: unknown }).$ref;\n    if (typeof ref === \"string\") {\n      const m = /^#\\/(?:\\$defs|definitions)\\/(.+)$/.exec(ref);\n      if (m && (!defs || !(m[1] in defs))) return false;\n    }\n    return Object.values(node).every(walk);\n  };\n  return walk(schema);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const t = fromJsonSchema(schema);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"unresolved $ref\")) {\n    throw new Error(`Add missing definition: ${err.message}`);\n  }\n  throw err;\n}","preventionTips":["Validate schemas against the JSON Schema metaschema (ajv) before conversion.","Check ref name spelling and casing against `$defs` keys.","Don't prune `$defs` entries when stripping schema documents."],"tags":["json-schema","ref","missing-definition"],"backgroundTag":"unresolved-schema-ref","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}