can1357/oh-my-pi · error · OmpTypeError

literal is excluded by the intersection

Error message

literal is excluded by the intersection

What it means

Thrown when intersecting a literal type with another type: `walk(b, a.v)` returns an OmpErrors validation failure, meaning the other type cannot ever accept the literal's value. The library refuses to construct the intersection because the literal is provably not a member of the other type.

Source

Thrown at packages/omptype/src/type.ts:2041

	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)}`,
					);
				}
				const defaulted = required ? undefined : ap.hasDefault ? ap : bp.hasDefault ? bp : undefined;
				props[index] = {

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the literal value satisfies the other type's constraints (domain, length, pattern)
  2. Update the literal or the other type so the value is accepted
  3. Replace the intersection with the literal alone if the other constraint is redundant
  4. Catch OmpTypeError at intersect time to report the conflicting literal

Example fix

// before
intersect(lit('https'), string().max(3));
// after
intersect(lit('https'), string().max(5));
Defensive patterns

Strategy: validation

Validate before calling

function literalFits(value, t) {
  const errs = walk(t, value); // or t.validate(value) equivalent
  return !(errs instanceof OmpErrors);
}
// guard: literalFits('a', otherType) before intersect(lit('a'), otherType)

Type guard

const isOmpTypeError = (e: unknown): e is OmpTypeError => e instanceof OmpTypeError;

Try / catch

try {
  const t = intersect(lit('a'), other);
} catch (err) {
  if (err instanceof OmpTypeError && err.message.includes('literal is excluded')) {
    // fall back to `other` alone or report the conflicting literal
  } else throw err;
}

Prevention

When it happens

Trigger: intersect(lit('a'), someType) where someType rejects 'a' — e.g. a literal intersected with a number type, a string constraint that excludes the literal (length/URL bounds), or a different literal.

Common situations: Refining a config key to a specific allowed value that conflicts with an enum/constraint added elsewhere; narrowing a version literal against a range that no longer includes it after an upgrade.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/2297b6d12f965a11. Report an issue: GitHub.