{"record":{"id":"b69073d3a755905a","repo":"grpc/grpc-java","slug":"predicate-must-have-one-of-single-predicate-or-m","errorCode":null,"errorMessage":"Predicate must have one of: single_predicate, or_matcher, and_matcher, not_matcher","messagePattern":"Predicate must have one of: single_predicate, or_matcher, and_matcher, not_matcher","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/internal/matcher/PredicateEvaluator.java","lineNumber":41,"sourceCode":"import java.util.ArrayList;\nimport java.util.List;\n\nabstract class PredicateEvaluator {\n  abstract boolean evaluate(MatchContext context);\n  \n  static PredicateEvaluator fromProto(Predicate proto) {\n    switch (proto.getMatchTypeCase()) {\n      case SINGLE_PREDICATE:\n        return new SinglePredicateEvaluator(proto.getSinglePredicate());\n      case OR_MATCHER:\n        return new OrMatcherEvaluator(proto.getOrMatcher());\n      case AND_MATCHER:\n        return new AndMatcherEvaluator(proto.getAndMatcher());\n      case NOT_MATCHER:\n        return new NotMatcherEvaluator(proto.getNotMatcher());\n      case MATCHTYPE_NOT_SET:\n      default:\n        throw new IllegalArgumentException(\n            \"Predicate must have one of: single_predicate, or_matcher, and_matcher, not_matcher\");\n    }\n  }\n\n  private static final class SinglePredicateEvaluator extends PredicateEvaluator {\n    private final MatchInput input;\n    private final Matcher matcher;\n    \n    SinglePredicateEvaluator(Predicate.SinglePredicate proto) {\n      if (!proto.hasInput()) {\n        throw new IllegalArgumentException(\"SinglePredicate must have input\");\n      }\n      this.input = UnifiedMatcher.resolveInput(proto.getInput());\n      \n      if (proto.hasValueMatch()) {\n        Matchers.StringMatcher stringMatcher =\n            MatcherParser.parseStringMatcher(proto.getValueMatch());\n        this.matcher = new StringMatcherAdapter(stringMatcher);","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/internal/matcher/PredicateEvaluator.java#L23-L59","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Populate one of the oneof fields (single_predicate, or_matcher, and_matcher, not_matcher) on every Predicate in the matcher config","Fix the upstream management server / config generator so it never emits MatchType-not-set predicates","Pre-validate each Predicate with proto.getMatchTypeCase() != MATCHTYPE_NOT_SET before invoking fromProto"],"exampleFix":"// before\nPredicate p = Predicate.newBuilder().build();\n// after\nPredicate p = Predicate.newBuilder()\n    .setSinglePredicate(SinglePredicate.newBuilder()\n        .setInput(input)\n        .setValueMatch(stringMatcher))\n    .build();","handlingStrategy":"validation","validationCode":"if (predicate.getMatchTypeCase() == Predicate.MatchTypeCase.MATCHTYPE_NOT_SET) {\n  throw new IllegalArgumentException(\"Predicate has no match type set\");\n}","typeGuard":null,"tryCatchPattern":"try { PredicateEvaluator.fromProto(p); } catch (IllegalArgumentException e) { log.error(\"Bad predicate: \" + e.getMessage()); throw new ConfigException(e); }","preventionTips":["Set exactly one of single_predicate/or_matcher/and_matcher/not_matcher per Predicate","Use proto builders that make the oneof explicit","Lint xDS configs for unset oneofs before deploy"],"tags":["xds","matcher","config-validation","grpc"],"backgroundTag":"missing-required-argument","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"}