{"record":{"id":"c7922eda3d07037e","repo":"can1357/oh-my-pi","slug":"tuple-length-intersection-is-unsatisfiable","errorCode":null,"errorMessage":"tuple length intersection is unsatisfiable","messagePattern":"tuple length intersection is unsatisfiable","errorType":"exception","errorClass":"OmpTypeError","httpStatus":null,"severity":"error","filePath":"packages/omptype/src/type.ts","lineNumber":1946,"sourceCode":"\t};\n}\n\nfunction intersectTuples(left: TupleIR, right: TupleIR): IR {\n\tif (\n\t\tleft.postfix.length !== 0 ||\n\t\tright.postfix.length !== 0 ||\n\t\tleft.prefix.some(item => item.hasDefault) ||\n\t\tright.prefix.some(item => item.hasDefault)\n\t) {\n\t\treturn { k: \"intersection\", members: [left, right] };\n\t}\n\tconst leftRequired = left.prefix.filter(item => !item.opt).length;\n\tconst rightRequired = right.prefix.filter(item => !item.opt).length;\n\tconst minimum = Math.max(leftRequired, rightRequired);\n\tconst leftMaximum = left.variadic === undefined ? left.prefix.length : Number.POSITIVE_INFINITY;\n\tconst rightMaximum = right.variadic === undefined ? right.prefix.length : Number.POSITIVE_INFINITY;\n\tconst maximum = Math.min(leftMaximum, rightMaximum);\n\tif (minimum > maximum) throw new OmpTypeError(\"tuple length intersection is unsatisfiable\");\n\n\tconst prefixLength = Number.isFinite(maximum) ? maximum : Math.max(left.prefix.length, right.prefix.length);\n\tconst prefix: TupleIR[\"prefix\"] = [];\n\tfor (let index = 0; index < prefixLength; index++) {\n\t\tconst leftItem = left.prefix[index];\n\t\tconst rightItem = right.prefix[index];\n\t\tconst leftNode = leftItem?.val ?? left.variadic;\n\t\tconst rightNode = rightItem?.val ?? right.variadic;\n\t\tif (leftNode === undefined || rightNode === undefined) break;\n\t\tconst required = (leftItem !== undefined && !leftItem.opt) || (rightItem !== undefined && !rightItem.opt);\n\t\ttry {\n\t\t\tprefix.push({ val: intersect(leftNode, rightNode), opt: !required });\n\t\t} catch (error) {\n\t\t\tif (required || !(error instanceof OmpTypeError)) throw error;\n\t\t\tbreak;\n\t\t}\n\t}\n\tconst variadic =","sourceCodeStart":1928,"sourceCodeEnd":1964,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/omptype/src/type.ts#L1928-L1964","documentation":"When intersecting two tuple types, omptype computes the length interval: the intersection's minimum is the max of both required-prefix lengths, its maximum the min of both maximum lengths. If minimum > maximum no tuple can satisfy both sides, so construction throws immediately instead of yielding an uninhabitable type.","triggerScenarios":"intersect(tuple([string, string, string]), tuple([string])) — one tuple requires 3 elements while the other allows at most 1; similarly tuple([a, optional(b)]) ∩ tuple([a, b, c]).","commonSituations":"Version-drift between two tuple definitions (one grew a field, the other didn't); intersecting a fixed tuple with a shorter one by mistake; config schema and payload schema diverging after a code change.","solutions":["Align tuple lengths so the shorter side can accept the longer side's required elements (pad with optional items or add a variadic)","Make trailing items optional: tuple([string, string, optional(number)]) instead of fixed length 3","If variable length is intended, give one side a rest element (...number()) so its maximum is infinite","Check which two schemas are being intersected; likely one is an outdated copy"],"exampleFix":"// before\nconst A = tuple([string, string]); const B = tuple([string]);\nintersect(A, B) // throws\n// after\nconst B = tuple([string, optional(string)]);\nintersect(A, B)","handlingStrategy":"try-catch","validationCode":"function tupleLengthCompatible(a, b) {\n  const minA = a.prefix.filter(i => !i.opt).length;\n  const minB = b.prefix.filter(i => !i.opt).length;\n  const maxA = a.variadic !== undefined ? Infinity : a.prefix.length;\n  const maxB = b.variadic !== undefined ? Infinity : b.prefix.length;\n  return Math.max(minA, minB) <= Math.min(maxA, maxB);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return intersect(tupleA, tupleB);\n} catch (err) {\n  if (err instanceof OmpTypeError && err.message.includes('tuple length')) {\n    logger.error('incompatible tuple lengths', { a: tupleA, b: tupleB });\n    return never();\n  }\n  throw err;\n}","preventionTips":["Keep tuple definitions in one shared module so versions can't drift","Make trailing tuple elements optional when lengths may vary","Compute length compatibility before intersecting programmatically-derived tuples"],"tags":["omptype","tuple","intersection","unsatisfiable"],"backgroundTag":"unsatisfiable-type-intersection","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}