{"record":{"id":"7138ec0cc2b90a03","repo":"apache/skywalking","slug":"unsupported-function","errorCode":null,"errorMessage":"Unsupported function.","messagePattern":"Unsupported function\\.","errorType":"exception","errorClass":"IllegalExpressionException","httpStatus":null,"severity":"error","filePath":"oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/LogicalFunctionOp.java","lineNumber":43,"sourceCode":"import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResultType;\nimport org.apache.skywalking.oap.server.core.query.mqe.MQEValue;\nimport org.apache.skywalking.oap.server.core.query.mqe.MQEValues;\nimport org.apache.skywalking.oap.server.library.util.CollectionUtils;\n\nimport java.util.Objects;\n\npublic class LogicalFunctionOp {\n\n    public static ExpressionResult doOP(int opType, MQEParser.ExpressionListContext expressionListContext,\n                                                       MQEParserBaseVisitor<ExpressionResult> visitor) throws IllegalExpressionException {\n        switch (opType) {\n            case MQEParser.VIEW_AS_SEQ:\n                return viewAsSeq(expressionListContext, visitor);\n            case MQEParser.IS_PRESENT:\n                return isPresent(expressionListContext, visitor);\n        }\n\n        throw new IllegalExpressionException(\"Unsupported function.\");\n    }\n\n    private static ExpressionResult viewAsSeq(MQEParser.ExpressionListContext expressionListContext,\n                                              MQEParserBaseVisitor<ExpressionResult> visitor) {\n        ExpressionResult firstResult = null;\n        for (MQEParser.ExpressionContext expContext : expressionListContext.expression()) {\n            final ExpressionResult result = visitor.visit(expContext);\n            if (firstResult == null) {\n                firstResult = result;\n            }\n            if (result == null || CollectionUtils.isEmpty(result.getResults())) {\n                continue;\n            }\n            final boolean isNotEmptyValue = result.getResults().stream()\n                .filter(s -> s != null && CollectionUtils.isNotEmpty(s.getValues()))\n                .flatMap(s -> s.getValues().stream()).anyMatch(s -> !s.isEmptyValue());\n            if (isNotEmptyValue) {\n                return result;","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/apache/skywalking/blob/102af09b4a56064e22050dded10e2c52e490d040/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/operation/LogicalFunctionOp.java#L25-L61","documentation":"LogicalFunctionOp.doOP dispatches on the parsed operator token: only VIEW_AS_SEQ and IS_PRESENT are supported. Any other token reaching the switch falls through to 'Unsupported function.' as an IllegalExpressionException. In practice the ANTLR grammar only routes those two tokens here, so this is a defensive guard against grammar/runtime drift or a new logical token added to the grammar without a runtime implementation.","triggerScenarios":"Executing an MQE expression whose logical function token is neither viewAsSeq nor isPresent — typically after the MQE grammar (mqe-grammar) was extended with a new logical function but mqe-rt was not updated, or when a custom OAP build mixes grammar and runtime versions.","commonSituations":"Custom OAP forks adding grammar rules without runtime handlers; upgrading only part of the MQE modules (grammar jar newer than runtime jar); malformed generated visitor dispatching an unexpected token type.","solutions":["Check the MQE expression uses only viewAsSeq(...) or isPresent(...) as logical functions","If you extended MQEParser with a new logical token, add its case to LogicalFunctionOp.doOP and rebuild mqe-rt","Ensure mqe-grammar and mqe-rt artifacts come from the same OAP version (no mixed jars in oap-libs)","Simplify the query to isolate which function token triggers the failure"],"exampleFix":"// before (custom grammar token without runtime support)\nquery: logicalNot(metric)\n// after\nquery: isPresent(metric)","handlingStrategy":"try-catch","validationCode":"// before evaluating, whitelist logical functions against the OAP's supported set\nSet<String> supported = Set.of(\"viewAsSeq\", \"isPresent\");","typeGuard":null,"tryCatchPattern":"catch (IllegalExpressionException e) { if (e.getMessage().contains(\"Unsupported function\")) { /* grammar/runtime skew or unsupported token */ } }","preventionTips":["Only use viewAsSeq/isPresent as logical functions","Keep mqe-grammar and mqe-rt jars at the same version","When forking the grammar, implement runtime cases in the same change"],"tags":["mqe","query-engine","grammar","unsupported-operation"],"backgroundTag":null,"analyzedSha":"102af09b4a56064e22050dded10e2c52e490d040","analyzedAt":"2026-08-14T10:47:52.647Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}