grpc/grpc-java · error · CelEvaluationException

Unsupported input type for CEL evaluation: ${input class nam

Error message

Unsupported input type for CEL evaluation: ${input class name or null}

What it means

CelStringExtractor.extract() evaluates the CEL program only when the input is a CelVariableResolver; for any other input type it must either return the configured defaultValue or, when no default was supplied, throw CelEvaluationException. The message reports 'null' or the offending class name. Unlike CelMatcher, extract() tolerates evaluation failures when a default exists, but unsupported input types with no default are fatal.

Source

Thrown at xds/src/main/java/io/grpc/xds/internal/matcher/CelStringExtractor.java:82

   * Evaluates the CEL expression and returns the string result.
   * Returns the default value if the result is not a string or if evaluation
   * fails.
   */
  String extract(Object input) throws CelEvaluationException {
    if (input instanceof CelVariableResolver) {
      try {
        Object result = program.eval((CelVariableResolver) input);

        if (result instanceof String) {
          return (String) result;
        }
      } catch (CelEvaluationException e) {
        if (defaultValue == null) {
          throw e;
        }
      }
    } else if (defaultValue == null) {
      throw new CelEvaluationException(
          "Unsupported input type for CEL evaluation: "
              + (input == null ? "null" : input.getClass().getName()));
    }
    return defaultValue;
  }
}

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Implement CelVariableResolver around your request context and pass that to extract().
  2. Supply a defaultValue (e.g. "unknown") when compiling so extraction degrades gracefully instead of throwing.
  3. Null-check input and construct a resolver before calling extract().

Example fix

// before
String v = extractor.extract(headersMap); // throws, no default
// after
String v = extractor.extract(new HeaderResolver(headersMap));
// or compile with a default:
CelStringExtractor.compile(ast, "unknown");
Defensive patterns

Strategy: fallback

Validate before calling

if (input == null || !(input instanceof CelVariableResolver)) {
  return defaultValue; // or build a resolver first
}

Type guard

boolean isExtractable(Object input) { return input instanceof CelVariableResolver; }

Try / catch

try { return extractor.extract(resolver); }
catch (CelEvaluationException e) { return defaultValue != null ? defaultValue : ""; }

Prevention

When it happens

Trigger: extract() is called with null or a non-CelVariableResolver object (e.g. a raw Map or proto) while defaultValue == null, so the else-branch throws. Tests extract_unsupportedInputType_throws and extract_evaluationError_throws cover these paths.

Common situations: Forgetting to supply a default value when wiring the extractor while passing non-resolver inputs; calling extract() from generic code that handles multiple input shapes; null headers/attributes on a request path.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/60a64e11fdab7d5b. Report an issue: GitHub.