gleam-lang/gleam · error
Tried to reduce without 2 guards
Error message
Tried to reduce without 2 guards
What it means
Same invariant as the expression reducer but for clause guards: `do_reduce_clause_guard` requires exactly two guard operands to combine with an operator. Fewer than two indicates the guard parser's stack bookkeeping broke, so it panics.
Solutions
- Extract the failing `case` clause guard into a minimal repro and file a Gleam compiler bug.
- When patching the parser, ensure guard operators always follow two pushed guards before reduction.
- Work around by rewriting the guard (e.g. splitting a compound guard into simpler ones or using a `let assert` / body-level check).
Example fix
// before (suspect guard)
case x { y if > 3 -> ... }
// after
case x { y if y > 3 -> ... } Defensive patterns
Strategy: try-catch
Try / catch
let parsed = std::panic::catch_unwind(|| parse_case(tokens));
match parsed {
Ok(case) => case,
_ => report_compiler_bug("Tried to reduce without 2 guards"),
} Prevention
- Write guards with explicit operands (e.g. `x if x > 3`) rather than unusual operand/operator orders.
- Report minimal failing `case` guards as compiler bugs.
- Keep guard parser push/pop pairs verified when editing parse.rs.
When it happens
Trigger: A clause-guard operator (e.g. `&&`, `||`, comparisons inside a `case` guard) is reduced while the guard stack contains fewer than two `UntypedClauseGuard` values, due to a guard-parsing bug or internals misuse.
Common situations: Gleam parser development/regressions around `case` expression guards; not normally triggerable by well-formed or even straightforwardly malformed user code.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Expression not fully reduced.
- invalid constants can not be in an untyped ast
- Token could not be converted to binop.
- Tried to reduce bit array size without 2 operands
- Tried to reduce without 2 expressions
AI-assisted analysis of gleam-lang/gleam@15b07c7830 (2026-09-14).
Data as JSON: /api/errors/c82aec21cf2e8d00.
Report an issue: GitHub.
Appendix: source
Thrown at compiler-core/src/parse.rs:5145
/// Simple-Precedence-Parser, perform reduction for expression
fn do_reduce_expression(operator: Spanned, estack: &mut Vec<UntypedExpr>) {
match (estack.pop(), estack.pop()) {
(Some(right), Some(left)) => {
let new_expression = expression_operator_reduction(operator, left, right);
estack.push(new_expression);
}
_ => panic!("Tried to reduce without 2 expressions"),
}
}
/// Simple-Precedence-Parser, perform reduction for clause guard
fn do_reduce_clause_guard(operator: Spanned, estack: &mut Vec<UntypedClauseGuard>) {
match (estack.pop(), estack.pop()) {
(Some(right), Some(left)) => {
let expression = clause_guard_reduction(operator, left, right);
estack.push(expression);
}
_ => panic!("Tried to reduce without 2 guards"),
}
}
/// Simple-Precedence-Parser, perform reduction for clause guard
fn do_reduce_constant(operator: Spanned, estack: &mut Vec<UntypedConstant>) {
match (estack.pop(), estack.pop()) {
(Some(left), Some(right)) => {
let new_expression = constant_binop_reduction(operator, right, left);
estack.push(new_expression);
}
_ => panic!("Tried to reduce without 2 guards"),
}
}
/// Simple-Precedence-Parser, perform reduction for bit array size expressions
fn reduce_bit_array_size((_, token, _): Spanned, experession_stack: &mut Vec<BitArraySize<()>>) {
let operator = token_to_bit_array_size_operator(&token)
.expect("only operator tokens are pushed onto the bit array size opstack");View on GitHub (pinned to 15b07c7830)