{"record":{"id":"70da16a71855c109","repo":"apache/skywalking","slug":"casttype-casttype-is-legal-context-expression","errorCode":null,"errorMessage":"castType:{castType} is legal, context expression:{originalExpression}","messagePattern":"castType:(.+?) is legal, context expression:(.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/v2/util/TypeCastUtil.java","lineNumber":39,"sourceCode":"public class TypeCastUtil {\n    /**\n     * @param castType           to change the value of given original expression.\n     * @param originalExpression to read the value\n     * @return cast expression if cast type exists and is legal.\n     */\n    public static String withCast(String castType, String originalExpression) {\n        if (castType == null) {\n            return originalExpression;\n        }\n        switch (castType) {\n            case \"(str->long)\":\n            case \"(long)\":\n                return \"Long.parseLong(\" + originalExpression + \")\";\n            case \"(str->int)\":\n            case \"(int)\":\n                return \"Integer.parseInt(\" + originalExpression + \")\";\n            default:\n                throw new IllegalArgumentException(\n                    \"castType:\" + castType + \" is legal, context expression:\" + originalExpression);\n        }\n    }\n}\n","sourceCodeStart":21,"sourceCodeEnd":44,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/oal-rt/src/main/java/org/apache/skywalking/oal/v2/util/TypeCastUtil.java#L21-L44","documentation":"TypeCastUtil.withCast wraps an OAL attribute expression with a Java cast call during code generation. Only '(str->long)', '(long)', '(str->int)' and '(int)' are recognized; anything else hits default and throws. (Note the message text says 'is legal' but it means 'is illegal' — a long-standing wording quirk.)","triggerScenarios":"An OAL expression uses an unsupported cast such as (str->double), (str->boolean), or a typo like (string->long). The grammar may accept the cast token but the code generator has no lowering for it.","commonSituations":"Trying to cast a string metric attribute to a type other than long/int (e.g. building a double metric from a tag); typo in the cast syntax; assuming SQL-style CAST semantics in OAL.","solutions":["Use only the supported casts: (str->long) / (long) and (str->int) / (int)","If a double/boolean conversion is needed, preprocess the value upstream (e.g. in MAL/LAL or the agent) so the OAL source attribute is already numeric","Remove the cast entirely if the attribute is already the right type"],"exampleFix":"// before (OAL)\nlatency = from Span.tag('lat')(str->double).avg() --> latencyAvg\n// after\nlatency = from Span.tag('lat')(str->long).avg() --> latencyAvg","handlingStrategy":"validation","validationCode":"// Lint OAL casts before deploy:\nSet<String> ok = Set.of(\"(str->long)\", \"(long)\", \"(str->int)\", \"(int)\");\nfor (String cast : castsUsed(script)) {\n    if (!ok.contains(cast)) throw new ConfigException(\"Unsupported OAL cast: \" + cast);\n}","typeGuard":null,"tryCatchPattern":"In OAL validation tooling, catch IllegalArgumentException from the enricher and surface it with the rule's file:line; do not catch in OAP startup.","preventionTips":["Remember OAL casts only convert strings to long/int — never double, boolean, or reverse","Read the message knowing 'is legal' actually means 'is illegal' (wording quirk) — the castType and expression in it are accurate"],"tags":["oal","type-cast","code-generation","validation"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}