can1357/oh-my-pi · error
schema contains unresolved $ref after dereferencing
Error message
schema contains unresolved $ref after dereferencing
What it means
The YieldTool constructor dereferences the caller-supplied JSON schema (dereferenceJsonSchema) before using it for structured output. If the resolved schema still contains unresolved $ref pointers (hasUnresolvedRefs), the constructor throws — meaning the schema references definitions that were never included, so structured-output providers would produce invalid requests.
Source
Thrown at packages/coding-agent/src/tools/yield.ts:329
if (strictProbe.strict) {
sanitizedSchema = sanitizeSchemaForStrictMode(normalizedSchema);
} else {
sanitizedSchema = normalizedSchema;
this.strict = false;
}
} else if (!schemaError && normalized === true) {
sanitizedSchema = {};
this.strict = false;
}
let dataSchema: Record<string, unknown>;
if (sanitizedSchema !== undefined) {
const resolved = dereferenceJsonSchema({
...sanitizedSchema,
description: schemaDescription,
}) as Record<string, unknown>;
if (hasUnresolvedRefs(resolved)) {
throw new Error("schema contains unresolved $ref after dereferencing");
}
dataSchema = withSectionVariants(resolved);
} else {
this.strict = false;
dataSchema = looseRecordSchema(
schemaError ? schemaDescription : "Structured JSON output (no schema specified)",
);
}
parameters = wrapYieldParameters(dataSchema);
JSON.stringify(parameters);
if (!isValidJsonSchema(parameters)) throw new Error("yield parameters schema is invalid");
} catch (err) {
const errorMsg = err instanceof Error ? err.message : String(err);
parameters = wrapYieldParameters(
looseRecordSchema(`Structured JSON output (schema processing failed: ${errorMsg})`),
);
validate = undefined;
this.strict = false;View on GitHub (pinned to 9690622007)
Solutions
- Inline the referenced definitions into the schema's `$defs`/`definitions`.
- Replace `$ref` with the fully expanded schema object (inline the target).
- Run a dereference/inlining step (e.g. ajv or $RefParser) on the schema before passing it.
- Remove the schema to fall back to loose record schema if strict structure isn't required.
Example fix
// before
yield({ schema: { type: "object", properties: { x: { $ref: "#/$defs/X" } } } })
// after
yield({ schema: { type: "object", properties: { x: { $ref: "#/$defs/X" } } }, $defs: { X: { type: "string" } } }) Defensive patterns
Strategy: validation
Validate before calling
function hasRefs(schema: object): boolean { return JSON.stringify(schema).includes('"$ref"'); } // if true, ensure all $defs are embedded before passing Type guard
function schemaRefsResolve(schema: { $ref?: string; $defs?: Record<string, unknown> }): boolean { return !schema.$ref || (schema.$defs != null && schema.$ref.startsWith("#/$defs/") && schema.$defs[schema.$ref.slice(8)] !== undefined); } Try / catch
try { const tool = new YieldTool({ schema }); } catch (e) { if (e.message === "schema contains unresolved $ref after dereferencing") { const inlined = inlineRefs(schema); const tool = new YieldTool({ schema: inlined }); } else throw e; } Prevention
- Bundle/inlne all $refs (ajv, @apidevtools/json-schema-ref-parser) before constructing YieldTool.
- Include $defs in the same document as the schema.
- Avoid external/URL $refs entirely for tool schemas.
- Validate the schema with a meta-schema validator up front.
When it happens
Trigger: Constructing YieldTool with a schema containing `$ref` pointers to definitions absent from the schema document (e.g. `#/$defs/Foo` with no $defs.Foo, or external `$ref` URLs).
Common situations: Passing a zod/ajv-serialized schema fragment whose `$defs` were in another document; hand-assembled schemas; reusing a sub-schema extracted from a larger spec.
Related errors
- yield parameters schema is invalid
- ${scope} does not match schema: ${formatAllValidationIssues(
- 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
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/fd9650c221c30850.
Report an issue: GitHub.