{"record":{"id":"a93228e2224d2e51","repo":"can1357/oh-my-pi","slug":"merge-requires-an-object-schema","errorCode":null,"errorMessage":"merge requires an object schema","messagePattern":"merge requires an object schema","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/type.ts","lineNumber":3245,"sourceCode":"\t}\n\tconst ir: IR = members.length === 0 ? { k: \"never\" } : members.length === 1 ? members[0] : { k: \"union\", members };\n\treturn makeType(ir, [], {});\n}\n\nfunction buildAnd(definitions: readonly unknown[], resolve?: AliasResolver): InternalType;\nfunction buildAnd<output, input>(definitions: readonly unknown[], resolve?: AliasResolver): FluentType<output, input>;\nfunction buildAnd(definitions: readonly unknown[], resolve?: AliasResolver): InternalType {\n\tif (definitions.length === 0) return makeType({ k: \"unknown\" }, [], {});\n\tlet ir = parseDef(definitions[0], resolve);\n\tfor (let index = 1; index < definitions.length; index++) {\n\t\tir = intersect(ir, parseDef(definitions[index], resolve));\n\t}\n\treturn makeType(ir, [], {});\n}\n\nfunction requireNaryObject(ir: IR): ObjectIR {\n\tconst resolved = resolveAlias(ir);\n\tif (resolved.k !== \"object\") throw new OmpTypeError(\"merge requires an object schema\");\n\treturn resolved;\n}\n\nfunction buildMerge(definitions: readonly unknown[], resolve?: AliasResolver): InternalType;\nfunction buildMerge<output, input>(definitions: readonly unknown[], resolve?: AliasResolver): FluentType<output, input>;\nfunction buildMerge(definitions: readonly unknown[], resolve?: AliasResolver): InternalType {\n\tif (definitions.length === 0) return makeType({ k: \"anyobject\" }, [], {});\n\tlet object = requireNaryObject(parseDef(definitions[0], resolve));\n\tfor (let index = 1; index < definitions.length; index++) {\n\t\tobject = mergeObjects(object, requireNaryObject(parseDef(definitions[index], resolve)));\n\t}\n\treturn makeType(object, [], {});\n}\n\nfunction buildPipe(definitions: readonly unknown[], resolve?: AliasResolver): InternalType;\nfunction buildPipe<output, input>(definitions: readonly unknown[], resolve?: AliasResolver): FluentType<output, input>;\nfunction buildPipe(definitions: readonly unknown[], resolve?: AliasResolver): InternalType {\n\tif (definitions.length === 0) return makeType({ k: \"unknown\" }, [], {});","sourceCodeStart":3227,"sourceCodeEnd":3263,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/type.ts#L3227-L3263","documentation":"Object-merging combinators (`merge` and related n-ary object operations) can only operate on schemas whose underlying IR is an object type. If any operand resolves to a non-object type (string, array, union, primitive), the operation is undefined and omptype throws.","triggerScenarios":"Passing a non-object schema to `type.merge(...)` or a composed merge, e.g. `type.merge({ a: \"string\" }, \"string[]\")`, or merging an alias that resolves to a primitive/union.","commonSituations":"Merging schema constants where one was changed to a union or array during refactoring; passing a morph/mapped type whose resolved kind is not object; dynamically assembling schemas from config where one entry is a primitive validator.","solutions":["Ensure every argument to merge is an object-typed schema (`type({...})` with object literal definition or `type` object blocks).","If an operand is a union of objects, merge the individual object members or pick one branch.","Check aliases referenced in the merge resolve to object definitions."],"exampleFix":"// before\ntype.merge({ a: \"string\" }, \"string[]\")\n// after\ntype.merge({ a: \"string\" }, { b: \"string[]\" })","handlingStrategy":"validation","validationCode":"const isObjectSchema = (t: unknown) => { try { return (t as { expression?: string }).expression !== undefined && typeof (t as { json?(): unknown }).json === 'function'; } catch { return false; } };","typeGuard":"const isMergeable = (t: unknown): boolean => { try { const r = (t as InternalType); return r.expression.startsWith('{'); } catch { return false; } };","tryCatchPattern":"try { const merged = type.merge(a, b); } catch (e) { if (e instanceof OmpTypeError && e.message.includes('merge requires an object schema')) logNonObjectOperand(); else throw e; }","preventionTips":["Only pass object-literal schemas to merge","Resolve aliases used in merges to confirm they are object types","Annotate schema constants with their kind so refactors to unions are caught early"],"tags":["schema","merge","object-type","validation"],"backgroundTag":"merge-requires-object-schema","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}