{"record":{"id":"7b30964668357d2d","repo":"BoundaryML/baml","slug":"unexpected-postfix-operator","errorCode":null,"errorMessage":"Unexpected postfix operator: {:?}","messagePattern":"Unexpected postfix operator: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-lib/ast/src/parser/parse_expression.rs","lineNumber":130,"sourceCode":"\n                        Rule::generic_fn_app => match parse_generic_fn_app(inner, diagnostics)? {\n                            Expression::App(fn_call) => Expression::MethodCall {\n                                receiver: Box::new(left),\n                                method: fn_call.name,\n                                args: fn_call.args,\n                                type_args: fn_call.type_args,\n                                span: span.clone(),\n                            },\n\n                            _ => {\n                                unreachable!(\"expected function call when parsing method call\")\n                            }\n                        },\n\n                        _ => unreachable!(\"Unexpected method call rule: {:?}\", inner.as_rule()),\n                    }\n                }\n                _ => unreachable!(\"Unexpected postfix operator: {:?}\", operator.as_rule()),\n            })\n        })\n        .map_infix(|left, operator, right| {\n            let operator = match operator.as_rule() {\n                Rule::EQ => BinaryOperator::Eq,\n                Rule::NEQ => BinaryOperator::Neq,\n                Rule::LT => BinaryOperator::Lt,\n                Rule::LTEQ => BinaryOperator::LtEq,\n                Rule::GT => BinaryOperator::Gt,\n                Rule::GTEQ => BinaryOperator::GtEq,\n                Rule::ADD => BinaryOperator::Add,\n                Rule::SUB => BinaryOperator::Sub,\n                Rule::MUL => BinaryOperator::Mul,\n                Rule::DIV => BinaryOperator::Div,\n                Rule::MOD => BinaryOperator::Mod,\n                Rule::BIT_AND => BinaryOperator::BitAnd,\n                Rule::BIT_OR => BinaryOperator::BitOr,\n                Rule::BIT_XOR => BinaryOperator::BitXor,","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/ast/src/parser/parse_expression.rs#L112-L148","documentation":"This is a `unreachable!()` panic from the fallback arm of `parse_config_map_key` in the BAML AST parser. The function iterates the children of a `config_map_key` pair, and after the loop it asserts that the key was definitely captured; reaching the trailing `unreachable!()` means every child rule fell through without assigning the key expression — a broken grammar/parser contract. Note the arm just above calls `unreachable_rule` (which reports a diagnostic and returns a placeholder), so this line should be impossible even on malformed input.","triggerScenarios":"Parsing a config map entry (e.g. inside a BAML client/llm config block) whose `config_map_key` pair contains only rules not matched by the loop's arms — e.g. after a grammar change renaming the key rules (`identifier`, `string_literal`) without updating `parse_config_map_key`.","commonSituations":"Writing config blocks with unusual keys (quoted or computed keys) in a BAML version where the key grammar changed; contributors editing baml.pest config-map rules without updating the key parser.","solutions":["Use a plain identifier as the config map key (e.g. `provider \"openai\"` style with simple names), not quoted/complex keys","Inspect the config entry at the panic span and rewrite the key in standard BAML config syntax","If you are a contributor: extend `parse_config_map_key`'s loop to cover all rules allowed for `config_map_key` in baml.pest","Upgrade BAML so the config key grammar and parser agree"],"exampleFix":"// before (unusual key form)\nclient MyClient {\n  \"api key setting\" \"value\"\n}\n// after\nclient MyClient {\n  api_key_setting \"value\"\n}","handlingStrategy":"validation","validationCode":"// Ensure config map keys are plain identifiers before writing BAML config:\nfunction assertPlainConfigKey(entry) {\n  if (!/^[A-Za-z_]\\w*$/.test(entry.key)) {\n    throw new Error(`Config map key '${entry.key}' is not a plain identifier; the BAML parser may panic`);\n  }\n}","typeGuard":"const isPlainIdentifierKey = (key) => typeof key === 'string' && /^[A-Za-z_]\\w*$/.test(key);","tryCatchPattern":"catch (panicOutput) {\n  if (String(panicOutput).includes('Encountered impossible config map key')) {\n    logParserBug('config_map_key produced no recognized child rule', panicOutput);\n    return null;\n  }\n  throw panicOutput;\n}","preventionTips":["Use simple identifier keys in client/llm/retriever config blocks","Extend parse_config_map_key whenever config_map_key grammar rules change","Fuzz config-block parsing when touching baml.pest config rules","Pin grammar and parser to the same release"],"tags":["parser","panic","config-map","rust"],"backgroundTag":"internal-invariant-violation","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}