can1357/oh-my-pi · error · OmpTypeError
unresolved $ref: ${ref}
Error message
unresolved $ref: ${ref} What it means
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.
Source
Thrown at packages/omptype/src/from-json-schema.ts:52
readonly #aliases = new Map<string, IR>();
constructor(root: JsonSchema) {
this.#root = root;
}
resolveRef(ref: string): IR {
const cached = this.#aliases.get(ref);
if (cached !== undefined) return cached;
let target: unknown;
if (ref === "#") {
target = this.#root;
} else {
const defsMatch = /^#\/(\$defs|definitions)\/(.+)$/.exec(ref);
if (defsMatch === null) throw new OmpTypeError(`unsupported $ref: ${ref}`);
const defs = this.#root[defsMatch[1]];
target = typeof defs === "object" && defs !== null ? (defs as JsonSchema)[defsMatch[2]] : undefined;
if (target === undefined) throw new OmpTypeError(`unresolved $ref: ${ref}`);
}
// Register the alias before lowering so recursive references resolve
// to the same node instead of recursing forever.
let lowered: IR | undefined;
const alias: IR = {
k: "alias",
name: ref,
resolve: () => {
lowered ??= this.lower(target);
return lowered;
},
};
this.#aliases.set(ref, alias);
return alias;
}
lower(schema: unknown): IR {View on GitHub (pinned to 9690622007)
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.
Example fix
// before
{ "type": "object", "properties": { "id": { "$ref": "#/$defs/Id" } } } // no $defs
// after
{ "type": "object", "properties": { "id": { "$ref": "#/$defs/Id" } }, "$defs": { "Id": { "type": "string" } } } Defensive patterns
Strategy: validation
Validate before calling
function refsResolve(schema: Record<string, unknown>): boolean {
const defs = (schema.$defs ?? schema.definitions) as Record<string, unknown> | undefined;
const walk = (node: unknown): boolean => {
if (typeof node !== "object" || node === null) return true;
const ref = (node as { $ref?: unknown }).$ref;
if (typeof ref === "string") {
const m = /^#\/(?:\$defs|definitions)\/(.+)$/.exec(ref);
if (m && (!defs || !(m[1] in defs))) return false;
}
return Object.values(node).every(walk);
};
return walk(schema);
} Try / catch
try {
const t = fromJsonSchema(schema);
} catch (err) {
if (err instanceof Error && err.message.startsWith("unresolved $ref")) {
throw new Error(`Add missing definition: ${err.message}`);
}
throw err;
} Prevention
- 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.
When it happens
Trigger: `{"$ref": "#/$defs/Missing"}` when `$defs` is empty, omitted, or lacks the key `Missing`; typo in the definition name; def stripped by a bundler/pruner.
Common situations: Hand-edited schemas with typos; code-generated schemas referencing defs that were filtered out; case-sensitivity mismatches (`#/$defs/user` vs `User`).
Related errors
- unsupported $ref: ${ref}
- Schema contains a circular object graph — cannot enforce str
- Schema node has no type, combinator, or $ref — cannot enforc
- Host tool "${name}" must provide a JSON Schema object
- Invalid ${scope} output schema: ${error}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/1be6a97bd1d7a7f0.
Report an issue: GitHub.