{"record":{"id":"7545c6a433fe418b","repo":"grpc/grpc-java","slug":"cel-expression-references-unsupported-named-functi","errorCode":null,"errorMessage":"CEL expression references unsupported named function: ","messagePattern":"CEL expression references unsupported named function: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/internal/matcher/CelCommon.java","lineNumber":128,"sourceCode":"                || ALLOWED_OVERLOAD_ID_PREFIX_PATTERN.matcher(id).matches()) {\n              allowed = true;\n              break;\n            }\n          }\n          if (!allowed) {\n            throw new IllegalArgumentException(\n                \"CEL expression references unknown function with overload IDs: \"\n                    + ref.overloadIds());\n          }\n        } else {\n          // Standard conversion functions (like string(x)) are named in the AST.\n          // We must explicitly reject 'string' here since it's disabled in the environment.\n          if (name.equals(\"string\")) {\n            throw new IllegalArgumentException(\n                \"CEL expression references unknown function with overload IDs: \"\n                    + ref.overloadIds());\n          }\n          throw new IllegalArgumentException(\n              \"CEL expression references unsupported named function: \" + name);\n        }\n      }\n    }\n  }\n}\n","sourceCodeStart":110,"sourceCodeEnd":135,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/internal/matcher/CelCommon.java#L110-L135","documentation":"Final branch of checkAllowedReferences: when a named function reference is neither allowlisted via overload IDs nor the explicitly-rejected string() conversion, it is rejected as an unsupported named function. This error names the exact function so developers know what is not available in the xDS CEL sandbox.","triggerScenarios":"A CEL expression calls any named function outside the allowed set (e.g., timestamp(), dyn(), extensions, or user-declared functions from another environment) — any name other than the permitted patterns.","commonSituations":"Porting CEL policies from other products (Envoy, OPA-style CEL) that enable richer function sets; relying on CEL extensions not enabled in gRPC-XDS matchers.","solutions":["Rewrite the expression using only the allowed core functions (comparison, size, membership, has())","Move unsupported logic into code that decides routing before/around the matcher","Consult the CEL environment declaration for the exact allowlist of functions","Split complex expressions into simpler allowed checks combined with && / ||"],"exampleFix":"// before\nCEL: timestamp(request.headers['x-ts']) > now\n// after — no timestamp function; do a string/size-based check instead\nCEL: has(request.headers['x-ts']) && request.headers['x-ts'] != ''","handlingStrategy":"try-catch","validationCode":"if (!Set.of(\"size\",\"has\",\"matches\",\"contains\",\"startsWith\",\"endsWith\").containsAll(extractFunctionNames(celSource))) {\n  throw new IllegalArgumentException(\"CEL uses unsupported named function\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  CelCommon.checkAllowedReferences(ast);\n} catch (IllegalArgumentException e) {\n  log.error(\"Unsupported CEL function: {}\", e.getMessage());\n}","preventionTips":["Restrict expressions to the documented CEL allowlist for xDS matchers","Rewrite Envoy/OPA CEL idioms before porting","Combine simple allowed checks instead of exotic functions","Validate expressions in CI against the same environment"],"tags":["grpc","xds","cel","function-allowlist"],"backgroundTag":"invalid-argument-value","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}