grpc/grpc-java · error · IllegalArgumentException
StringMatcher expected a String input, but received
Error message
StringMatcher expected a String input, but received: ${value class name} What it means
The adapter exposing StringMatcher as a generic Matcher only accepts String values. If evaluate() hands it a non-String (non-null) value, it throws this IllegalArgumentException naming the actual received class, since StringMatcher.matches only understands strings.
Solutions
- Fix the MatchInput so it outputs a String (or its outputType() declaration matches the matcher's expected String input)
- Replace value_match with a custom_match whose matcher accepts the input's actual type
- Wrap custom inputs so they stringify their output before reaching StringMatcher
Example fix
// before
public Object evaluate(MatchContext ctx) {
return ctx.request().headerCount(); // Integer into StringMatcher
}
// after
public Object evaluate(MatchContext ctx) {
return String.valueOf(ctx.request().headerCount());
} Defensive patterns
Strategy: type-guard
Validate before calling
if (matcher.inputType() != String.class && !(value instanceof String)) {
throw new IllegalStateException("StringMatcher fed non-String value");
} Type guard
static boolean isStringValue(Object v) { return v instanceof String; } Try / catch
try { boolean r = evaluator.evaluate(ctx); } catch (IllegalArgumentException e) { log.error("Matcher input type error: " + e.getMessage()); return MatchResult.noMatch(); } Prevention
- Make MatchInput.outputType() reflect the real runtime type produced
- Unit-test custom MatchInputs against their declared output types
- Avoid dynamic inputs that can return varying types
When it happens
Trigger: Running a matcher tree where a SinglePredicate's input produces a non-String value (e.g. an integer or boolean output from a custom MatchInput) but the matcher is a StringMatcherAdapter wrapping a StringMatcher; type checks at construction passed or were bypassed.
Common situations: Custom MatchInput implementations whose outputType() claim doesn't match the produced runtime type; config where value_match is combined with a binary/numeric input; reflection or dynamic input resolution returning unexpected types.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Type mismatch: input
- AndMatcher must have at least 2 predicates
- CEL expression must evaluate to boolean, got:
- HttpAttributesCelMatchInput cannot be used with MatcherTree
- Invalid message type
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/22064815c8a7d5f3.
Report an issue: GitHub.
Appendix: source
Thrown at xds/src/main/java/io/grpc/xds/internal/matcher/PredicateEvaluator.java:100
return matcher.match(input.apply(context));
}
private static final class StringMatcherAdapter implements Matcher {
private final Matchers.StringMatcher stringMatcher;
StringMatcherAdapter(Matchers.StringMatcher stringMatcher) {
this.stringMatcher = stringMatcher;
}
@Override
public boolean match(Object value) {
if (value == null) {
return false;
}
if (!(value instanceof String)) {
throw new IllegalArgumentException(
"StringMatcher expected a String input, but received: "
+ value.getClass().getName());
}
return stringMatcher.matches((String) value);
}
@Override
public Class<?> inputType() {
return String.class;
}
}
}
private static final class OrMatcherEvaluator extends PredicateEvaluator {
private final List<PredicateEvaluator> evaluators;
OrMatcherEvaluator(Predicate.PredicateList proto) {
if (proto.getPredicateCount() < 2) {View on GitHub (pinned to 64daddc1f3)