grpc/grpc-java · error · IllegalArgumentException

Predicate must have one of: single_predicate, or_matcher, an

Error message

Predicate must have one of: single_predicate, or_matcher, and_matcher, not_matcher

What it means

PredicateEvaluator.fromProto converts a Predicate proto into a runtime evaluator by switching on its match_type oneof. If the oneof is MATCHTYPE_NOT_SET (or hits the default branch), no evaluator can be built, so it throws this IllegalArgumentException.

Source

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

import java.util.ArrayList;
import java.util.List;

abstract class PredicateEvaluator {
  abstract boolean evaluate(MatchContext context);
  
  static PredicateEvaluator fromProto(Predicate proto) {
    switch (proto.getMatchTypeCase()) {
      case SINGLE_PREDICATE:
        return new SinglePredicateEvaluator(proto.getSinglePredicate());
      case OR_MATCHER:
        return new OrMatcherEvaluator(proto.getOrMatcher());
      case AND_MATCHER:
        return new AndMatcherEvaluator(proto.getAndMatcher());
      case NOT_MATCHER:
        return new NotMatcherEvaluator(proto.getNotMatcher());
      case MATCHTYPE_NOT_SET:
      default:
        throw new IllegalArgumentException(
            "Predicate must have one of: single_predicate, or_matcher, and_matcher, not_matcher");
    }
  }

  private static final class SinglePredicateEvaluator extends PredicateEvaluator {
    private final MatchInput input;
    private final Matcher matcher;
    
    SinglePredicateEvaluator(Predicate.SinglePredicate proto) {
      if (!proto.hasInput()) {
        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);

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Populate one of the oneof fields (single_predicate, or_matcher, and_matcher, not_matcher) on every Predicate in the matcher config
  2. Fix the upstream management server / config generator so it never emits MatchType-not-set predicates
  3. Pre-validate each Predicate with proto.getMatchTypeCase() != MATCHTYPE_NOT_SET before invoking fromProto

Example fix

// before
Predicate p = Predicate.newBuilder().build();
// after
Predicate p = Predicate.newBuilder()
    .setSinglePredicate(SinglePredicate.newBuilder()
        .setInput(input)
        .setValueMatch(stringMatcher))
    .build();
Defensive patterns

Strategy: validation

Validate before calling

if (predicate.getMatchTypeCase() == Predicate.MatchTypeCase.MATCHTYPE_NOT_SET) {
  throw new IllegalArgumentException("Predicate has no match type set");
}

Try / catch

try { PredicateEvaluator.fromProto(p); } catch (IllegalArgumentException e) { log.error("Bad predicate: " + e.getMessage()); throw new ConfigException(e); }

Prevention

When it happens

Trigger: Calling PredicateEvaluator.fromProto with a Predicate proto whose match_type field was never set — i.e. the proto message exists but none of single_predicate, or_matcher, and_matcher, or not_matcher was populated, such as a Predicate constructed only via builder without calling setSinglePredicate/setOrMatcher/etc.

Common situations: Management servers emitting empty predicate entries; partial config generation where predicate lists contain placeholder messages; proto deserialization from configs that omitted the oneof field entirely.

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/b69073d3a755905a. Report an issue: GitHub.