{"record":{"id":"03d7c495bbf255df","repo":"can1357/oh-my-pi","slug":"unsupported-ref-ref","errorCode":null,"errorMessage":"unsupported $ref: ${ref}","messagePattern":"unsupported \\$ref: (.+?)","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/from-json-schema.ts","lineNumber":49,"sourceCode":"\nclass Importer {\n\treadonly #root: JsonSchema;\n\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;","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/from-json-schema.ts#L31-L67","documentation":"`fromJsonSchema` only supports root refs (`#`) and local definition refs of the form `#/$defs/Name` or `#/definitions/Name`. Any other `$ref` syntax (external URLs, escaped pointers, nested pointer paths) throws this `OmpTypeError`. The library deliberately does not resolve remote or arbitrary JSON-pointer refs.","triggerScenarios":"Passing a JSON Schema whose `$ref` is e.g. `\"http://example.com/schema\"`, `\"#/definitions/a/b\"`, `\"#/definitions/A/properties/x\"`, or `\"other.json#/definitions/A\"` to `fromJsonSchema`.","commonSituations":"Schemas generated by tools that emit external refs (`$id`-based references); OpenAPI documents with `components` refs; schemas with escaped-pointer keys (`~0`, `~1`).","solutions":["Rewrite the schema so all `$ref`s point to `#/$defs/Name` or `#/definitions/Name` in the same document.","Pre-resolve external/nested refs yourself (bundle the schema with a tool like `@apidevtools/json-schema-ref-parser`) before conversion.","Inline the referenced subschema at the ref site if bundling isn't possible."],"exampleFix":"// before\n{ \"$ref\": \"http://example.com/common.json#/definitions/Id\" }\n// after\n{ \"$ref\": \"#/$defs/Id\" } // with \"Id\" defined in $defs of the same schema","handlingStrategy":"validation","validationCode":"function hasOnlySupportedRefs(schema: { $ref?: string } & Record<string, unknown>): boolean {\n  if (typeof schema.$ref === \"string\" && !/^#\\/(\\$defs|definitions)\\/[^/]+$/.test(schema.$ref)) return false;\n  return Object.values(schema).every(v => typeof v !== \"object\" || v === null || hasOnlySupportedRefs(v as never));\n}","typeGuard":null,"tryCatchPattern":"try {\n  const t = fromJsonSchema(schema);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"unsupported $ref\")) {\n    throw new Error(`Bundle schema first: ${err.message}`);\n  }\n  throw err;\n}","preventionTips":["Bundle/dereference schemas (json-schema-ref-parser) before converting.","Restrict schema authors to local `$defs` refs.","Avoid escaped-pointer keys and nested pointer refs in shared schemas."],"tags":["json-schema","ref","unsupported"],"backgroundTag":"unsupported-json-schema-ref","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}