apache/skywalking · error · IllegalArgumentException
MAL expression parsing failed while injecting expPrefix: {}
Error message
MAL expression parsing failed while injecting expPrefix: {} in expression: {} What it means
Thrown by MALScriptParser.injectExpPrefix when the base expression in a rule's exp: field fails to parse with the MAL ANTLR grammar while the compiler is splicing the file-level expPrefix (e.g. tag({tags -> ...})) into every metric source. The error listener accumulates line:column messages from ANTLR, and any syntax error aborts injection before text splicing happens.
Source
Thrown at oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALScriptParser.java:135
final MALLexer lexer = new MALLexer(CharStreams.fromString(exp));
final CommonTokenStream tokens = new CommonTokenStream(lexer);
final MALParser parser = new MALParser(tokens);
final List<String> errors = new ArrayList<>();
parser.removeErrorListeners();
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(final Recognizer<?, ?> recognizer,
final Object offendingSymbol,
final int line,
final int charPositionInLine,
final String msg,
final RecognitionException e) {
errors.add(line + ":" + charPositionInLine + " " + msg);
}
});
final MALParser.ExpressionContext tree = parser.expression();
if (!errors.isEmpty()) {
throw new IllegalArgumentException(
"MAL expression parsing failed while injecting expPrefix: "
+ String.join("; ", errors) + " in expression: " + exp);
}
final List<int[]> ranges = new ArrayList<>();
collectMetricSourceRanges(tree, ranges);
// Splice from right to left so earlier indices remain valid.
ranges.sort(Comparator.comparingInt((int[] r) -> r[0]).reversed());
final StringBuilder sb = new StringBuilder(exp);
for (final int[] range : ranges) {
final String name = sb.substring(range[0], range[1] + 1);
sb.replace(range[0], range[1] + 1, "(" + name + "." + expPrefix + ")");
}
return sb.toString();
}
private static void collectMetricSourceRanges(final ParseTree node,
final List<int[]> ranges) {
if (node instanceof MALParser.PrimaryContext) {View on GitHub (pinned to 102af09b4a)
Solutions
- Read the line:column in the message — it locates the syntax error in the exp: string itself
- Fix the expression grammar (balance parens/brackets, double-quote strings, use supported operators)
- Sanity-parse the expression in isolation (unit test with MALScriptParser.parse or the MalRuleLoader.formatExp helper) to separate exp errors from expPrefix errors
- Check for invisible characters from copy-paste (smart quotes, non-breaking spaces)
Example fix
# before exp: http_success_request.sum(['idc'].service(['idc']) # after exp: http_success_request.sum(['idc']).service(['idc'])
Defensive patterns
Strategy: try-catch
Validate before calling
// fail early in tests before deploying
try {
String combined = MALScriptParser.injectExpPrefix(exp, expPrefix);
} catch (IllegalArgumentException e) {
throw new AssertionError("Bad exp: " + e.getMessage());
} Try / catch
catch IllegalArgumentException around injectExpPrefix/formatExp in a rule-loading harness; report file + rule name, and fail the deployment rather than skipping the rule silently
Prevention
- Run all custom rule YAMLs through a parse test (MalRuleLoader.formatExp + DSL.parse) in CI
- Prefer per-rule expressions over clever file-level expPrefix blocks to keep failures isolated
- Use a YAML-aware editor and lint unbalanced brackets
When it happens
Trigger: MetricConvert.formatExp calls injectExpPrefix(exp, expPrefix); it throws when the exp text has a grammar error — unbalanced parentheses, a stray character, an unsupported operator, or an identifier that does not lex as a metric source. Note this fires on the raw exp BEFORE prefix splicing, so the prefix itself is usually not the culprit.
Common situations: Hand-editing an otel-rules/meter-analyzer-config YAML and breaking the expression (missing ')', using '||' where MAL only supports specific boolean ops, smart quotes pasted from a doc); files that set a file-level expPrefix make every rule in the file go through this path, so one bad expr surfaces with this message.
Related errors
- MAL expression parsing failed: {} in expression: {}
- MAL filter expression parsing failed: {} in expression: {}
- Load meter analyzer configs failed
- {slot} value '{numText}' exceeds the supported range (must f
- Unclosed interpolation in: {s}
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/e3c756af58e162f2.
Report an issue: GitHub.