{"record":{"id":"bc94299a41b73e9e","repo":"BoundaryML/baml","slug":"expected-function-call-when-parsing-method-call","errorCode":null,"errorMessage":"expected function call when parsing method call","messagePattern":"expected function call when parsing method call","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-lib/ast/src/parser/parse_expression.rs","lineNumber":109,"sourceCode":"\n                    Expression::FieldAccess(Box::new(left), field, span.clone())\n                }\n\n                Rule::method_call => {\n                    let inner = operator.into_inner().next()?;\n\n                    match inner.as_rule() {\n                        Rule::fn_app => match parse_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                        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()),","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/ast/src/parser/parse_expression.rs#L91-L127","documentation":"This is a `unreachable!()` panic in `parse_expression`'s postfix method-call handling in the BAML AST parser. When the grammar rule `fn_app` is parsed as a postfix operator (a method call `receiver.method(...)`), the result of `parse_fn_call` must be an `Expression::App`; any other variant breaks the contract and the parser panics. This indicates the function-call parser returned something other than a call expression.","triggerScenarios":"Parsing `receiver.method(args)` where `parse_fn_app(inner, diagnostics)` returns a non-`App` expression variant — e.g. after `parse_fn_call` is changed to return `Expression::Identifier` or `Expression::MethodCall` in some path.","commonSituations":"Contributors refactoring `parse_fn_call`/`parse_fn_app` so it can return variants other than `App`; running a mismatched grammar/parser build where the `fn_app` rule produces unexpected shapes while parsing chained method calls on strings, arrays, or maps.","solutions":["Simplify the offending method call expression in the BAML source (e.g. split chained calls into intermediate variables) to bypass the mis-parse","Check the BAML source at the panic span for unusual method-call syntax (generics on methods, chained calls) and rewrite it in a plainer form","If you are a contributor: make `parse_fn_call` return `Expression::App` unconditionally on the `fn_app` path, or handle other variants instead of `unreachable!()`","Upgrade BAML to a build where fn_app parsing and this match agree"],"exampleFix":"// before (may hit the panic)\nlet v = obj.method1().method2();\n// after\nlet a = obj.method1();\nlet v = a.method2();","handlingStrategy":"validation","validationCode":"// Avoid exotic method-call shapes before parsing:\nfunction assertSimpleMethodCall(expr) {\n  if (/\\.\\s*[\\w<>]+\\s*\\(/.test(expr) && (expr.match(/\\./g) || []).length > 2) {\n    throw new Error('Deeply chained method calls may hit a parser invariant; simplify: ' + expr);\n  }\n}","typeGuard":"const isAppCall = (parsed) => parsed && parsed.type === 'App';","tryCatchPattern":"catch (panicOutput) {\n  if (String(panicOutput).includes('expected function call when parsing method call')) {\n    logParserBug('parse_fn_app returned non-App expression', panicOutput);\n    return null;\n  }\n  throw panicOutput;\n}","preventionTips":["Keep method-call chains short; assign intermediates to variables","Only use parse_fn_app results as Expression::App when contributing","Add round-trip tests for chained method calls","Align baml grammar and parser versions"],"tags":["parser","panic","method-call","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"}