can1357/oh-my-pi · error · OmpTypeError
ParseError: Invalid intersection of default values ${String(
Error message
ParseError: Invalid intersection of default values ${String(ap.def)} & ${String(bp.def)} What it means
When intersecting two object types that share a property key where BOTH sides declare a default value and those defaults differ (by Object.is), the intersection cannot pick a single default, so the library throws. Intersections must yield one deterministic default for each property.
Source
Thrown at packages/omptype/src/type.ts:2054
}
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)}`,
);
}
const defaulted = required ? undefined : ap.hasDefault ? ap : bp.hasDefault ? bp : undefined;
props[index] = {
key: ap.key,
opt: ap.opt && bp.opt,
val: intersect(ap.val, bp.val),
...(defaulted
? {
def: defaulted.def,
defFactory: defaulted.defFactory,
hasDefault: true,
defValidated: defaulted.defValidated,
}
: {}),
};
}View on GitHub (pinned to 9690622007)
Solutions
- Make the defaults identical on both sides
- Remove .default() from one of the two operands so only one side supplies a default
- Merge the schemas at the source (one canonical definition) instead of intersecting
- Catch OmpTypeError and report which key/defaults conflict
Example fix
// before
intersect(object({retries: number().opt().default(3)}), object({retries: number().opt().default(5)}));
// after
intersect(object({retries: number().opt().default(3)}), object({retries: number().opt()})); Defensive patterns
Strategy: validation
Validate before calling
function hasConflictingDefaults(a, b, key) {
const pa = a.props?.find(p => p.key === key);
const pb = b.props?.find(p => p.key === key);
return pa?.hasDefault && pb?.hasDefault && !Object.is(pa.def, pb.def);
} Type guard
const isOmpTypeError = (e: unknown): e is OmpTypeError => e instanceof OmpTypeError;
Try / catch
try {
const merged = intersect(baseSchema, overrideSchema);
} catch (err) {
if (err instanceof OmpTypeError && err.message.startsWith('ParseError: Invalid intersection of default values')) {
logger.warn('conflicting defaults in schema intersection', { message: err.message });
} else throw err;
} Prevention
- Give each option exactly one .default() — declare defaults only in the base schema
- Centralize schema definitions; do not copy-paste object fragments that both add defaults
- When overriding, use a plain optional property (opt()) instead of re-declaring a default
- Add a schema-build smoke test that intersects all shipped schema pairs
When it happens
Trigger: intersect(object({retries: opt(number).default(3)}), object({retries: opt(number).default(5)})) — same key, two different .default(...) values; typically from merging two schema definitions of the same object.
Common situations: Base schema and override schema both specifying .default() for the same option with different values; a vendor schema and a local refinement both defaulting a field; copy-pasted schema fragments drifting apart.
Related errors
- intersection has no satisfiable branches
- 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/c7ef0e3991a85c8e.
Report an issue: GitHub.