{"record":{"id":"4101ee9d992a4a7e","repo":"apache/skywalking","slug":"mal-expression-parsing-failed-in-expression","errorCode":null,"errorMessage":"MAL expression parsing failed: {} in expression: {}","messagePattern":"MAL expression parsing failed: (.+?) in expression: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALScriptParser.java","lineNumber":235,"sourceCode":"        final MALParser parser = new MALParser(tokens);\n\n        final List<String> errors = new ArrayList<>();\n        parser.removeErrorListeners();\n        parser.addErrorListener(new BaseErrorListener() {\n            @Override\n            public void syntaxError(final Recognizer<?, ?> recognizer,\n                                    final Object offendingSymbol,\n                                    final int line,\n                                    final int charPositionInLine,\n                                    final String msg,\n                                    final RecognitionException e) {\n                errors.add(line + \":\" + charPositionInLine + \" \" + msg);\n            }\n        });\n\n        final MALParser.ExpressionContext tree = parser.expression();\n        if (!errors.isEmpty()) {\n            throw new IllegalArgumentException(\n                \"MAL expression parsing failed: \" + String.join(\"; \", errors)\n                    + \" in expression: \" + expression);\n        }\n\n        return new MALExprVisitor().visit(tree.additiveExpression());\n    }\n\n    /**\n     * Parse a standalone filter closure expression into a {@link ClosureArgument}.\n     *\n     * @param filterExpression e.g. {@code \"{ tags -> tags.job_name == 'mysql-monitoring' }\"}\n     */\n    public static ClosureArgument parseFilter(final String filterExpression) {\n        final MALLexer lexer = new MALLexer(CharStreams.fromString(filterExpression));\n        final CommonTokenStream tokens = new CommonTokenStream(lexer);\n        final MALParser parser = new MALParser(tokens);\n\n        final List<String> errors = new ArrayList<>();","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALScriptParser.java#L217-L253","documentation":"Generic MAL expression parse failure: MALScriptParser.parse ran the ANTLR parser over an expression (the rule's combined expPrefix+exp+expSuffix text in production), the error listener collected one or more syntax errors, and parsing aborted with IllegalArgumentException carrying the accumulated line:column messages. This is the top-level 'your MAL expression is not grammatically valid' error.","triggerScenarios":"Any grammar violation in the final expression string: unbalanced parentheses, wrong quoting (single vs double quotes outside closures), unsupported operators, missing commas in argument lists, malformed Layer enum references, or an expSuffix scope function typed incorrectly.","commonSituations":"Authoring or editing otel-rules/*.yaml, meter-analyzer-config, telegraf/zabbix rule files; version upgrades that tightened the grammar (v1 Groovy accepted expressions the v2 ANTLR grammar rejects); YAML escaping issues where '>' or quotes get mangled.","solutions":["Use the line:column prefix in the message to locate the offending token in the expression printed after 'in expression:'","Compare with a known-good rule in the same directory (e.g. otel-rules vm.yaml) for quoting and structure","Rebuild the full combined expression via MetricConvert.formatExp logic (expPrefix + exp + expSuffix) when testing locally so you see exactly what the parser sees","Wrap a unit test around DSL.parse / MALScriptParser.parse to iterate quickly without restarting OAP"],"exampleFix":"# before\nexp: cpu_usage.sum(['mode']) .avg(['host']\n\n# after\nexpr: cpu_usage.sum(['mode']).avg(['host'])","handlingStrategy":"try-catch","validationCode":"try {\n    MALScriptParser.parse(expression);\n} catch (IllegalArgumentException | IllegalStateException e) {\n    throw new AssertionError(\"MAL syntax error: \" + e.getMessage());\n}","typeGuard":null,"tryCatchPattern":"catch IllegalArgumentException/IllegalStateException from DSL.parse; log metricName + full expression + cause, and stop OAP so the bad rule cannot be half-loaded","preventionTips":["Validate every rule file with the DSL test harness before merge","Diff rule files against a known-good baseline after upgrades — grammar tightens between versions","Read the line:column prefix — ANTLR messages locate the error precisely"],"tags":["mal","parser","antlr","syntax","configuration"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}