grpc/grpc-java · error · IllegalArgumentException

SinglePredicate must have either value_match or custom_match

Error message

SinglePredicate must have either value_match or custom_match

What it means

A SinglePredicate must specify exactly one of value_match or custom_match as its test condition. If neither is set, SinglePredicateEvaluator has no matcher to run and throws this IllegalArgumentException.

Source

Thrown at xds/src/main/java/io/grpc/xds/internal/matcher/PredicateEvaluator.java:70

        throw new IllegalArgumentException("SinglePredicate must have input");
      }
      this.input = UnifiedMatcher.resolveInput(proto.getInput());
      
      if (proto.hasValueMatch()) {
        Matchers.StringMatcher stringMatcher =
            MatcherParser.parseStringMatcher(proto.getValueMatch());
        this.matcher = new StringMatcherAdapter(stringMatcher);
      } else if (proto.hasCustomMatch()) {
        TypedExtensionConfig customConfig = proto.getCustomMatch();
        MatcherProvider provider = MatcherRegistry.getDefaultRegistry()
            .getMatcherProvider(customConfig.getTypedConfig().getTypeUrl());
        if (provider == null) {
          throw new IllegalArgumentException("Unsupported custom_match matcher: " 
              + customConfig.getTypedConfig().getTypeUrl());
        }
        this.matcher = provider.getMatcher(customConfig);
      } else {
        throw new IllegalArgumentException(
            "SinglePredicate must have either value_match or custom_match");
      }

      if (!input.outputType().equals(matcher.inputType())) {
        throw new IllegalArgumentException("Type mismatch: input " + input.outputType().getName()
            + " not compatible with matcher " + matcher.inputType().getName());
      }
    }
    
    @Override 
    boolean evaluate(MatchContext context) {
      return matcher.match(input.apply(context));
    }
    


    private static final class StringMatcherAdapter implements Matcher {
      private final Matchers.StringMatcher stringMatcher;

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Populate value_match (StringMatcher: exact/prefix/regex/safe_regex etc.) or custom_match on the SinglePredicate
  2. Validate hasValueMatch() || hasCustomMatch() during pre-parse config checks
  3. Fix the config producer so every single_predicate carries a match condition

Example fix

// before
single_predicate:
  input:
    typed_config:
      '@type': type.googleapis.com/grpc.xds.Input.MyHeaderInput
// after
single_predicate:
  input:
    typed_config:
      '@type': type.googleapis.com/grpc.xds.Input.MyHeaderInput
  value_match:
    exact: expected-value
Defensive patterns

Strategy: validation

Validate before calling

if (!singlePredicate.hasValueMatch() && !singlePredicate.hasCustomMatch()) {
  throw new IllegalArgumentException("single_predicate needs value_match or custom_match");
}

Try / catch

try { new PredicateEvaluator.SinglePredicateEvaluator(proto); } catch (IllegalArgumentException e) { log.error("Invalid predicate config: " + e.getMessage()); }

Prevention

When it happens

Trigger: Building a SinglePredicateEvaluator from a proto where hasValueMatch() is false and hasCustomMatch() is false — e.g. only the input was configured, or the match value block was deleted/never populated.

Common situations: Truncated or templated xDS configs; control-plane generators emitting input-only predicates; manual edits that removed the match condition while keeping the input.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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