apache/skywalking · error · IllegalArgumentException
Expected number argument for extension function
Error message
Expected number argument for extension function
What it means
Second-stage numeric check in MALMethodChainCodegen.generateExtensionArg: the argument IS an ExprArgument, but the inner expression is not a NumberExpr — the MAL grammar produced something like a boolean/null/identifier expression where the extension's numeric parameter needs a constant number literal that can be emitted as raw Java source.
Source
Thrown at oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALMethodChainCodegen.java:202
.append('"');
} else {
throw new IllegalArgumentException(
"Expected String argument for extension function, got "
+ arg.getClass().getSimpleName());
}
} else if (expectedType == double.class || expectedType == Double.class
|| expectedType == float.class || expectedType == Float.class
|| expectedType == long.class || expectedType == Long.class
|| expectedType == int.class || expectedType == Integer.class) {
if (!(arg instanceof MALExpressionModel.ExprArgument)) {
throw new IllegalArgumentException(
"Expected number argument for extension function, got "
+ arg.getClass().getSimpleName());
}
final MALExpressionModel.Expr expr =
((MALExpressionModel.ExprArgument) arg).getExpr();
if (!(expr instanceof MALExpressionModel.NumberExpr)) {
throw new IllegalArgumentException(
"Expected number argument for extension function");
}
final double raw =
((MALExpressionModel.NumberExpr) expr).getValue();
if (expectedType == double.class || expectedType == Double.class) {
sb.append(raw);
} else if (expectedType == float.class
|| expectedType == Float.class) {
sb.append((float) raw).append('F');
} else if (expectedType == long.class
|| expectedType == Long.class) {
sb.append((long) raw).append('L');
} else {
sb.append((int) raw);
}
} else if (List.class.isAssignableFrom(expectedType)) {
if (arg instanceof MALExpressionModel.StringListArgument) {
final List<String> values =View on GitHub (pinned to 102af09b4a)
Solutions
- Replace the argument with a constant numeric literal
- If you need dynamic values, do the computation inside the extension method body (e.g. read it from the SampleFamily or configuration) rather than as a MAL argument
- Restructure the rule so the extension receives the metric via the implicit SampleFamily parameter
Example fix
# before expr: m.sum([]).myext::scale(m2) # after expr: m.sum([]).myext::scale(2.0) # constants only; compute dynamics inside the extension
Defensive patterns
Strategy: type-guard
Type guard
boolean isConstantNumber(MALExpressionModel.Argument a) {
return a instanceof MALExpressionModel.ExprArgument
&& ((MALExpressionModel.ExprArgument) a).getExpr()
instanceof MALExpressionModel.NumberExpr;
} Try / catch
catch IllegalArgumentException at compile time; tell the author extension params must be constant literals
Prevention
- Remember extension extra params are compile-time constants inlined into generated code — no metric references
- Push dynamic logic inside the extension method body instead
When it happens
Trigger: '.myext::scale(otherMetric)' (identifier reference), '.myext::scale(true)', or any non-numeric expression passed to a double/int/long/float parameter. Only constant number literals can be inlined into the generated static call.
Common situations: Trying to parameterize an extension with another metric or a computed expression — extension extra params must be compile-time constants; passing YAML-inherited booleans.
Related errors
- Expected String argument for extension function, got {}
- Expected number argument for extension function, got {}
- Expected list argument for extension function, got {}
- Unknown MAL extension function: {}::{}
- MAL extension {}::{} expects {} argument(s), got {}
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/5b519dba7fad40dd.
Report an issue: GitHub.