{"record":{"id":"494a7447b4e34c1e","repo":"can1357/oh-my-pi","slug":"onundeclaredkey-requires-an-object-schema","errorCode":null,"errorMessage":"onUndeclaredKey requires an object schema","messagePattern":"onUndeclaredKey requires an object schema","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/type.ts","lineNumber":1877,"sourceCode":"\t}\n\treturn {\n\t\tk: \"object\",\n\t\tprops,\n\t\tindex: right.index ?? left.index,\n\t\tsymbolIndex: right.symbolIndex ?? left.symbolIndex,\n\t\tpatternIndexes:\n\t\t\tleft.patternIndexes === undefined && right.patternIndexes === undefined\n\t\t\t\t? undefined\n\t\t\t\t: [...(left.patternIndexes ?? []), ...(right.patternIndexes ?? [])],\n\t\textras: right.extras === \"keep\" ? left.extras : right.extras,\n\t};\n}\n\nfunction withShallowExtras(ir: IR, extras: ObjectIR[\"extras\"]): IR {\n\tif (ir.k === \"object\") return { ...ir, extras };\n\tif (ir.k === \"union\") return { ...ir, members: ir.members.map(member => withShallowExtras(member, extras)) };\n\tif (ir.k === \"alias\") return withShallowExtras(ir.resolve(), extras);\n\tthrow new OmpTypeError(\"onUndeclaredKey requires an object schema\");\n}\n\nfunction withDeepExtras(ir: IR, extras: ObjectIR[\"extras\"]): IR {\n\tswitch (ir.k) {\n\t\tcase \"object\":\n\t\t\treturn {\n\t\t\t\t...ir,\n\t\t\t\textras,\n\t\t\t\tprops: ir.props.map(prop => ({ ...prop, val: withDeepExtras(prop.val, extras) })),\n\t\t\t\tindex: ir.index === undefined ? undefined : withDeepExtras(ir.index, extras),\n\t\t\t\tsymbolIndex: ir.symbolIndex === undefined ? undefined : withDeepExtras(ir.symbolIndex, extras),\n\t\t\t\tpatternIndexes: ir.patternIndexes?.map(index => ({\n\t\t\t\t\tkey: withDeepExtras(index.key, extras),\n\t\t\t\t\tval: withDeepExtras(index.val, extras),\n\t\t\t\t})),\n\t\t\t};\n\t\tcase \"array\":\n\t\t\treturn { ...ir, el: withDeepExtras(ir.el, extras) };","sourceCodeStart":1859,"sourceCodeEnd":1895,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/type.ts#L1859-L1895","documentation":"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.","triggerScenarios":"string().onUndeclaredKey('delete'), array(...).onUndeclaredKey(...), or a morph/intersection schema passed to onUndeclaredKey.","commonSituations":"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).","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"],"exampleFix":"// before\narray(itemSchema).onUndeclaredKey('strip')\n// after\narray(itemSchema.onUndeclaredKey('strip'))","handlingStrategy":"type-guard","validationCode":"function assertObjectSchema(schema) {\n  if (typeof schema?.assert !== 'function') throw new Error('not an omptype schema');\n  // try a round-trip to confirm object-shaped:\n  try { schema.assert({}); } catch { /* object types may reject {} — acceptable */ }\n}","typeGuard":"function isObjectSchema(t): t is InternalType {\n  return typeof t === 'object' && t !== null && (t.ir?.k === 'object' || t.ir?.k === 'union' || t.ir?.k === 'alias');\n}","tryCatchPattern":"try {\n  return schema.onUndeclaredKey('strip');\n} catch (err) {\n  if (err instanceof OmpTypeError && err.message.includes('onUndeclaredKey requires an object schema')) {\n    throw new Error('apply onUndeclaredKey to the inner object schema, not the wrapper');\n  }\n  throw err;\n}","preventionTips":["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"],"tags":["omptype","object","undeclared-keys","api-misuse"],"backgroundTag":"api-called-on-wrong-schema-kind","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}