can1357/oh-my-pi · error · OmpTypeError
expected literal after == in "${this.#src}"
Error message
expected literal after == in "${this.#src}" What it means
The '==' equality constraint requires a num, bigint, or date literal immediately after it, but another token kind appeared. Unlike bounds, '==' does not accept date-vs-num mixing excuses — the operand must be one of those literal token types, so identifiers, strings, booleans, and end-of-input all throw.
Source
Thrown at packages/omptype/src/ir.ts:455
}
if (t2.v === ">" || t2.v === ">=") {
throw new OmpTypeError(`right bound must use < or <= in "${this.#src}"`);
}
this.#pos++;
const hi = this.#next();
if (hi.t !== "num" && hi.t !== "date") {
throw new OmpTypeError(`expected bound after comparator in "${this.#src}"`);
}
node = applyBound(node, t2.v, hi.v, this.#src);
return this.#eatArraySuffixes(node);
}
let node = this.#eatDivisor(this.parsePostfix());
const t2 = this.#peek();
if (t2?.t === "op" && t2.v === "==") {
this.#pos++;
const limit = this.#next();
if (limit.t !== "num" && limit.t !== "bigint" && limit.t !== "date") {
throw new OmpTypeError(`expected literal after == in "${this.#src}"`);
}
node = applyEquality(node, limit.v, this.#src);
} else if (t2?.t === "op" && CMP[t2.v] && (this.#peek(1)?.t === "num" || this.#peek(1)?.t === "date")) {
this.#pos++;
const limit = this.#next() as Extract<Tok, { t: "num" | "date" }>;
node = applyBound(node, t2.v, limit.v, this.#src);
node = this.#eatArraySuffixes(node);
}
return node;
}
#eatDivisor(node: IR): IR {
if (!this.#eatOp("%")) return node;
const divisor = this.#next();
if (divisor.t !== "num") throw new OmpTypeError(`expected number after % in "${this.#src}"`);
if (node.k !== "number") throw new OmpTypeError(`% requires number in "${this.#src}"`);
if (!Number.isFinite(divisor.v) || !Number.isInteger(divisor.v) || divisor.v === 0)
throw new OmpTypeError(`divisor must be a non-zero integer in "${this.#src}"`);View on GitHub (pinned to 9690622007)
Solutions
- Use a literal operand: 'number == 5', "'a' == 'a'", 'bigint == 10n', 'Date == d"2024-01-01"'.
- Stringify numbers before interpolation and never quote them; validate the interpolated value with Number.isFinite/typeof first.
- For non-numeric equality, use the appropriate literal syntax (quoted string, true/false keyword) or the corresponding keyword type instead of '=='.
- If the operand is dynamic, build the schema via the object/IR API where values are passed as data, not parsed text.
Example fix
// before
schema.parse(`number == ${value}`); // value = "x" -> throws
// after
if (!Number.isFinite(value)) throw new Error("value must be numeric");
schema.parse(`number == ${value}`); Defensive patterns
Strategy: validation
Validate before calling
function assertEqualityOperand(v) {
const ok = typeof v === "number" || typeof v === "bigint" || v instanceof Date;
if (!ok) throw new Error(`== operand must be num/bigint/date literal, got ${typeof v}`);
} Type guard
function isEqualityLiteral(v) {
return typeof v === "number" || typeof v === "bigint" || v instanceof Date;
} Try / catch
try {
const schema = parse(def);
} catch (e) {
if (String(e.message).includes("expected literal after ==")) {
// coerce the operand to a literal or switch to the value-based API
}
throw e;
} Prevention
- Only place numeric, bigint (n-suffixed), or date literals after '=='.
- Validate interpolated equality operands are finite numbers before composing the string.
- For string/boolean equality, use quoted literals or true/false keywords in the appropriate slot instead.
When it happens
Trigger: 'number == x' (identifier), "'a' == 'b'" where the right side is fine but 'number == "5"' (string token) fails, 'number ==' at end of input, 'boolean == 1'.
Common situations: Interpolating variable names into definitions expecting them to resolve at runtime; quoting the equality operand; building 'field == value' strings where value was never stringified into a literal.
Related errors
- Malformed number literal '${raw}'
- unexpected character '${c}' in "${src}"
- unexpected end of definition "${this.#src}"
- unsupported default literal in "${this.#src}"
- trailing tokens in definition "${this.#src}"
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/12e6f0ebb2584581.
Report an issue: GitHub.