can1357/oh-my-pi · error · OmpTypeError
onUndeclaredKey requires an object schema
Error message
onUndeclaredKey requires an object schema
What it means
withShallowExtras() can only attach onUndeclaredKey behavior to object-shaped IR (spreading shallowly through unions/aliases). If after resolution the schema is not an object (or a union/alias of objects), there is nowhere to attach key handling, so omptype throws.
Source
Thrown at packages/omptype/src/type.ts:1877
}
return {
k: "object",
props,
index: right.index ?? left.index,
symbolIndex: right.symbolIndex ?? left.symbolIndex,
patternIndexes:
left.patternIndexes === undefined && right.patternIndexes === undefined
? undefined
: [...(left.patternIndexes ?? []), ...(right.patternIndexes ?? [])],
extras: right.extras === "keep" ? left.extras : right.extras,
};
}
function withShallowExtras(ir: IR, extras: ObjectIR["extras"]): IR {
if (ir.k === "object") return { ...ir, extras };
if (ir.k === "union") return { ...ir, members: ir.members.map(member => withShallowExtras(member, extras)) };
if (ir.k === "alias") return withShallowExtras(ir.resolve(), extras);
throw new OmpTypeError("onUndeclaredKey requires an object schema");
}
function withDeepExtras(ir: IR, extras: ObjectIR["extras"]): IR {
switch (ir.k) {
case "object":
return {
...ir,
extras,
props: ir.props.map(prop => ({ ...prop, val: withDeepExtras(prop.val, extras) })),
index: ir.index === undefined ? undefined : withDeepExtras(ir.index, extras),
symbolIndex: ir.symbolIndex === undefined ? undefined : withDeepExtras(ir.symbolIndex, extras),
patternIndexes: ir.patternIndexes?.map(index => ({
key: withDeepExtras(index.key, extras),
val: withDeepExtras(index.val, extras),
})),
};
case "array":
return { ...ir, el: withDeepExtras(ir.el, extras) };View on GitHub (pinned to 9690622007)
Solutions
- Call onUndeclaredKey on the object schema itself: type({...}).onUndeclaredKey('delete')
- If you need it inside a collection, apply it to the element schema: array(type({...}).onUndeclaredKey('strip'))
- For unions, ensure every member is an object; extract the object member you meant
- Verify the schema variable holds an object type, not a transformed/morph result
Example fix
// before
array(itemSchema).onUndeclaredKey('strip')
// after
array(itemSchema.onUndeclaredKey('strip')) Defensive patterns
Strategy: type-guard
Validate before calling
function assertObjectSchema(schema) {
if (typeof schema?.assert !== 'function') throw new Error('not an omptype schema');
// try a round-trip to confirm object-shaped:
try { schema.assert({}); } catch { /* object types may reject {} — acceptable */ }
} Type guard
function isObjectSchema(t): t is InternalType {
return typeof t === 'object' && t !== null && (t.ir?.k === 'object' || t.ir?.k === 'union' || t.ir?.k === 'alias');
} Try / catch
try {
return schema.onUndeclaredKey('strip');
} catch (err) {
if (err instanceof OmpTypeError && err.message.includes('onUndeclaredKey requires an object schema')) {
throw new Error('apply onUndeclaredKey to the inner object schema, not the wrapper');
}
throw err;
} Prevention
- Apply onUndeclaredKey at the innermost object definition
- Don't chain it onto array()/record()/morph wrappers
- Re-check chains after refactoring a schema from object to array or union
When it happens
Trigger: string().onUndeclaredKey('delete'), array(...).onUndeclaredKey(...), or a morph/intersection schema passed to onUndeclaredKey.
Common situations: Chaining onUndeclaredKey on the wrong schema in a fluent chain; applying it to a union that contains a non-object branch after refactoring; forgetting the outer type is wrapped (e.g. array of objects).
Related errors
- date bounds require a Date type
- No messages to continue from
- Cannot continue from message role: assistant
- Gemini Files API cannot delete a handle from another provide
- Gemini Files API delete requires a valid file name
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/494a7447b4e34c1e.
Report an issue: GitHub.