{"record":{"id":"9a07e3bc0d6d3339","repo":"gleam-lang/gleam","slug":"tried-to-reduce-without-2-expressions","errorCode":null,"errorMessage":"Tried to reduce without 2 expressions","messagePattern":"Tried to reduce without 2 expressions","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-core/src/parse.rs","lineNumber":5134,"sourceCode":"        | Token::Macro\n        | Token::Opaque\n        | Token::Panic\n        | Token::Pub\n        | Token::Test\n        | Token::Todo\n        | Token::Type\n        | Token::Use => None,\n    }\n}\n\n/// Simple-Precedence-Parser, perform reduction for expression\nfn do_reduce_expression(operator: Spanned, estack: &mut Vec<UntypedExpr>) {\n    match (estack.pop(), estack.pop()) {\n        (Some(right), Some(left)) => {\n            let new_expression = expression_operator_reduction(operator, left, right);\n            estack.push(new_expression);\n        }\n        _ => panic!(\"Tried to reduce without 2 expressions\"),\n    }\n}\n\n/// Simple-Precedence-Parser, perform reduction for clause guard\nfn do_reduce_clause_guard(operator: Spanned, estack: &mut Vec<UntypedClauseGuard>) {\n    match (estack.pop(), estack.pop()) {\n        (Some(right), Some(left)) => {\n            let expression = clause_guard_reduction(operator, left, right);\n            estack.push(expression);\n        }\n        _ => panic!(\"Tried to reduce without 2 guards\"),\n    }\n}\n\n/// Simple-Precedence-Parser, perform reduction for clause guard\nfn do_reduce_constant(operator: Spanned, estack: &mut Vec<UntypedConstant>) {\n    match (estack.pop(), estack.pop()) {\n        (Some(left), Some(right)) => {","sourceCodeStart":5116,"sourceCodeEnd":5152,"githubUrl":"https://github.com/gleam-lang/gleam/blob/15b07c783065c92bb016b1b74ed0995a5259850f/compiler-core/src/parse.rs#L5116-L5152","documentation":"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.","triggerScenarios":"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.","commonSituations":"Parser development or regressions in Gleam's infix expression handling; essentially unreachable from ordinary user input since normal syntax errors return proper errors.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let parsed = std::panic::catch_unwind(|| parse_expression(tokens));\nmatch parsed {\n    Ok(Some(expr)) => expr,\n    _ => report_compiler_bug(\"Tried to reduce without 2 expressions\"),\n}","preventionTips":["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."],"tags":["parser","panic","stack-imbalance","internal-invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"15b07c783065c92bb016b1b74ed0995a5259850f","analyzedAt":"2026-09-14T11:14:59.388Z","contentChangedAt":"2026-09-14T11:14:59.388Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}