can1357/oh-my-pi · error · OmpTypeError
type.withJsonSchema cannot wrap schemas with defaults or out
Error message
type.withJsonSchema cannot wrap schemas with defaults or output-changing morphs
What it means
`type.withJsonSchema(schema, json)` attaches JSON Schema metadata to a type, but it cannot faithfully represent types that carry input defaults or output-changing morphs/pipes: those change the value between input and output, and attaching a static JSON Schema would misrepresent them. Such schemas are rejected at wrap time.
Source
Thrown at packages/omptype/src/type.ts:3697
/**
* Return a validation-only schema that emits `json` verbatim — even when
* embedded in an object, array, or union.
*
* A `.toJsonSchema()` method override cannot survive nesting: a parent schema
* emits each child's IR directly and never calls the child's method, so the
* override silently disappears from the wire schema. This stores the override
* on the IR instead.
*
* # Errors
*
* Throws when `schema` has a default or output-changing morph/pipe. A refine
* can preserve validation and the input value, but silently discarding a
* transformed output would violate the returned {@link Type}.
*/
export function withJsonSchema<t, i = t>(schema: Type<t, i>, json: Record<string, unknown>): Type<t, i> {
const internal = schema as unknown as InternalType;
if (internal.hasDefault || hasMorph(internal.ir) || internal[kSteps].some(step => step.kind === "pipe")) {
throw new OmpTypeError("type.withJsonSchema cannot wrap schemas with defaults or output-changing morphs");
}
return makeType<t, i>(
{
k: "refine",
base: { k: "unknown" },
pred: value => {
const result = schema(value);
return result instanceof OmpErrors ? result : true;
},
expected: schema.expression,
json: { ...json },
},
[],
{},
);
}
}
View on GitHub (pinned to 9690622007)
Solutions
- Remove `.default(...)` from the schema, or attach the JSON Schema before adding the default.
- Split morphs out: attach the JSON Schema to the pure validation base type, and apply the morph outside the wrapped type.
- Replace pipes with plain refinements (predicates that do not transform) if the output equals the input.
- Write the JSON Schema by hand for morphing types instead of using withJsonSchema.
Example fix
// before
type.withJsonSchema(type("string").pipe(s => s.trim()), {})
// after
type.withJsonSchema(type("string"), {}).pipe(s => s.trim()) Defensive patterns
Strategy: try-catch
Validate before calling
const canAttachJsonSchema = (schema: unknown) => { const t = schema as InternalType; return !t.hasDefault && !t.expression?.includes('=>'); }; Try / catch
try { return type.withJsonSchema(schema, json); } catch (e) { if (e instanceof OmpTypeError) return stripMorphsThenWrap(schema, json); throw e; } Prevention
- Attach JSON Schema metadata to pure validation types before adding defaults or pipes
- Keep morphs outside schemas destined for JSON Schema export
- Maintain a separate 'export shape' schema for docs generation when the runtime schema morphs
When it happens
Trigger: Calling `type.withJsonSchema(schema, {...})` where the schema was built with `.default(...)`, contains a morph (`.pipe(...)`, `.narrow` returning transformed values), or includes a piped step in its compiled steps.
Common situations: Retrofitting JSON Schema export onto an existing schema collection where some schemas have defaults added by later edits; piping in a transformation before trying to export the schema for docs/OpenAPI generation.
Related errors
- Schema contains a circular object graph — cannot enforce str
- Schema node has no type, combinator, or $ref — cannot enforc
- ParseError: Invalid intersection of default values ${String(
- anthropic-messages: ${data.summary}
- Anthropic cache refresh response omitted usage
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/bea283eb419ad0fa.
Report an issue: GitHub.