{"record":{"id":"5b519dba7fad40dd","repo":"apache/skywalking","slug":"expected-number-argument-for-extension-function","errorCode":null,"errorMessage":"Expected number argument for extension function","messagePattern":"Expected number argument for extension function","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/MALMethodChainCodegen.java","lineNumber":202,"sourceCode":"                  .append('\"');\n            } else {\n                throw new IllegalArgumentException(\n                    \"Expected String argument for extension function, got \"\n                        + arg.getClass().getSimpleName());\n            }\n        } else if (expectedType == double.class || expectedType == Double.class\n                || expectedType == float.class || expectedType == Float.class\n                || expectedType == long.class || expectedType == Long.class\n                || expectedType == int.class || expectedType == Integer.class) {\n            if (!(arg instanceof MALExpressionModel.ExprArgument)) {\n                throw new IllegalArgumentException(\n                    \"Expected number argument for extension function, got \"\n                        + arg.getClass().getSimpleName());\n            }\n            final MALExpressionModel.Expr expr =\n                ((MALExpressionModel.ExprArgument) arg).getExpr();\n            if (!(expr instanceof MALExpressionModel.NumberExpr)) {\n                throw new IllegalArgumentException(\n                    \"Expected number argument for extension function\");\n            }\n            final double raw =\n                ((MALExpressionModel.NumberExpr) expr).getValue();\n            if (expectedType == double.class || expectedType == Double.class) {\n                sb.append(raw);\n            } else if (expectedType == float.class\n                    || expectedType == Float.class) {\n                sb.append((float) raw).append('F');\n            } else if (expectedType == long.class\n                    || expectedType == Long.class) {\n                sb.append((long) raw).append('L');\n            } else {\n                sb.append((int) raw);\n            }\n        } else if (List.class.isAssignableFrom(expectedType)) {\n            if (arg instanceof MALExpressionModel.StringListArgument) {\n                final List<String> values =","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/v2/compiler/MALMethodChainCodegen.java#L184-L220","documentation":"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.","triggerScenarios":"'.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.","commonSituations":"Trying to parameterize an extension with another metric or a computed expression — extension extra params must be compile-time constants; passing YAML-inherited booleans.","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"],"exampleFix":"# before\nexpr: m.sum([]).myext::scale(m2)\n\n# after\nexpr: m.sum([]).myext::scale(2.0)  # constants only; compute dynamics inside the extension","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"boolean isConstantNumber(MALExpressionModel.Argument a) {\n    return a instanceof MALExpressionModel.ExprArgument\n        && ((MALExpressionModel.ExprArgument) a).getExpr()\n            instanceof MALExpressionModel.NumberExpr;\n}","tryCatchPattern":"catch IllegalArgumentException at compile time; tell the author extension params must be constant literals","preventionTips":["Remember extension extra params are compile-time constants inlined into generated code — no metric references","Push dynamic logic inside the extension method body instead"],"tags":["mal","extension","type-mismatch","codegen"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}