gleam-lang/gleam · error
Tried to reduce without 2 expressions
Error message
Tried to reduce without 2 expressions
What it means
In the expression precedence parser, `do_reduce_expression` pops two operands to combine with an operator. If fewer than two expressions are on the stack (malformed operator/operand interleaving), the parser's internal invariant is broken and it panics instead of producing a user-facing parse error.
Solutions
- Minimize the failing source snippet and report it as a Gleam parser bug.
- If patching the parser, verify each operator's handling pushes/pops operands in matched pairs.
- Reformat the expression with explicit parentheses as a possible workaround.
Defensive patterns
Strategy: try-catch
Try / catch
let parsed = std::panic::catch_unwind(|| parse_expression(tokens));
match parsed {
Ok(Some(expr)) => expr,
_ => report_compiler_bug("Tried to reduce without 2 expressions"),
} Prevention
- Report the minimal failing snippet to the Gleam repository.
- Add parentheses around complex infix expressions when a panic appears after a compiler upgrade.
- In parser code, assert stack depth before reductions in debug builds to catch imbalances early.
When it happens
Trigger: An operator reduction is triggered when the expression stack holds fewer than two `UntypedExpr` values — e.g. a binary operator encountered after an operand was consumed incorrectly or an operator handler miscounted pushes/pops.
Common situations: Parser development or regressions in Gleam's infix expression handling; essentially unreachable from ordinary user input since normal syntax errors return proper errors.
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 guards
AI-assisted analysis of gleam-lang/gleam@15b07c7830 (2026-09-14).
Data as JSON: /api/errors/9a07e3bc0d6d3339.
Report an issue: GitHub.
Appendix: source
Thrown at compiler-core/src/parse.rs:5134
| Token::Macro
| Token::Opaque
| Token::Panic
| Token::Pub
| Token::Test
| Token::Todo
| Token::Type
| Token::Use => None,
}
}
/// 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)) => {View on GitHub (pinned to 15b07c7830)