can1357/oh-my-pi · error · OmpTypeError
intersection has no satisfiable branches
Error message
intersection has no satisfiable branches
What it means
This error is thrown by the intersection algorithm in packages/omptype when combining two intersection-typed values: every candidate branch combination fails with an OmpTypeError, so no satisfiable member remains. The library treats an intersection whose branches are all impossible as a type-construction error rather than silently producing `never`, so it fails fast at type build/parse time.
Source
Thrown at packages/omptype/src/type.ts:2037
}
const schema = a.schema as InternalType;
return embed(makeType(intersect(schema.ir, b), schema[kSteps], metaOf(schema)));
}
if (b.k === "sub" && b.schema.hasSteps) return intersect(b, a);
if (a.k === "union" || b.k === "union") {
const union = a.k === "union" ? a : b.k === "union" ? b : undefined;
if (union === undefined) throw new OmpTypeError("union intersection invariant failed");
const branches = union.members;
const other = a.k === "union" ? b : a;
const members: IR[] = [];
for (const branch of branches) {
try {
members.push(intersect(branch, other));
} catch (error) {
if (!(error instanceof OmpTypeError)) throw error;
}
}
if (members.length === 0) throw new OmpTypeError("intersection has no satisfiable branches");
return members.length === 1 ? members[0] : { k: "union", members };
}
if (a.k === "lit") {
if (walk(b, a.v) instanceof OmpErrors) throw new OmpTypeError("literal is excluded by the intersection");
return a;
}
if (b.k === "lit") return intersect(b, a);
if (a.k === "object" && b.k === "object") {
const props = [...a.props];
for (const bp of b.props) {
const index = props.findIndex(prop => prop.key === bp.key);
if (index < 0) props.push(bp);
else {
const ap = props[index];
const required = (!ap.opt && !ap.hasDefault) || (!bp.opt && !bp.hasDefault);
if (ap.hasDefault && bp.hasDefault && !Object.is(ap.def, bp.def)) {
throw new OmpTypeError(
`ParseError: Invalid intersection of default values ${String(ap.def)} & ${String(bp.def)}`,View on GitHub (pinned to 9690622007)
Solutions
- Remove or relax one of the intersected types so at least one branch combination is satisfiable
- Check that both operands share the same value domain (string vs string, number vs number) before intersecting
- Catch OmpTypeError around the intersect call and surface which pair of types failed
- If the intersection is intentionally impossible, use a union or a single type instead
Example fix
// before const t = intersect(string().min(5), string().max(2)); // after const t = intersect(string().min(1), string().max(2));
Defensive patterns
Strategy: try-catch
Validate before calling
function canIntersect(a, b) {
try { intersect(a, b); return true; } catch (e) {
return e instanceof OmpTypeError ? false : throw e;
}
} Type guard
const isOmpTypeError = (e: unknown): e is OmpTypeError => e instanceof OmpTypeError;
Try / catch
let combined;
try {
combined = intersect(typeA, typeB);
} catch (err) {
if (err instanceof OmpTypeError) {
throw new Error(`Cannot intersect ${describe(typeA)} with ${describe(typeB)}: ${err.message}`);
}
throw err;
} Prevention
- Confirm both operands share the same base kind before intersecting
- Prefer single-builder constraints (.min/.max on one type) over intersecting two constrained types
- Add a unit test for every schema intersection you ship
- Catch OmpTypeError at schema-construction time and fail fast with both type descriptions
When it happens
Trigger: Calling the intersect/intersection helper (or building a schema that intersects two types) where every pairwise intersect(branch, other) call throws an OmpTypeError — e.g. intersecting string with number, or object shapes with conflicting required keys.
Common situations: Merging two config schemas that declare incompatible base types for the same option; combining a base type with a refinement whose domain no longer overlaps after a library upgrade; intersecting a tuple with mismatched element types.
Related errors
- ParseError: Invalid intersection of default values ${String(
- literal is excluded by the intersection
- intersection of ${a.expected} and ${b.expected} is unsatisfi
- intersection of ${leftDomain} and ${rightDomain} is unsatisf
- mapped property ${String(property.key)} has invalid kind
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/20f2f7929351ff7b.
Report an issue: GitHub.