{"record":{"id":"61cfef8bbb7f4090","repo":"grpc/grpc-java","slug":"singlepredicate-must-have-input","errorCode":null,"errorMessage":"SinglePredicate must have input","messagePattern":"SinglePredicate must have input","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/internal/matcher/PredicateEvaluator.java","lineNumber":52,"sourceCode":"        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);\n      } else if (proto.hasCustomMatch()) {\n        TypedExtensionConfig customConfig = proto.getCustomMatch();\n        MatcherProvider provider = MatcherRegistry.getDefaultRegistry()\n            .getMatcherProvider(customConfig.getTypedConfig().getTypeUrl());\n        if (provider == null) {\n          throw new IllegalArgumentException(\"Unsupported custom_match matcher: \" \n              + customConfig.getTypedConfig().getTypeUrl());\n        }\n        this.matcher = provider.getMatcher(customConfig);\n      } else {\n        throw new IllegalArgumentException(","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/internal/matcher/PredicateEvaluator.java#L34-L70","documentation":"A SinglePredicate pairs a MatchInput (the value source) with a Matcher (the test applied to that value). The input field is mandatory; if the proto lacks it, SinglePredicateEvaluator throws this IllegalArgumentException because there is nothing to evaluate against.","triggerScenarios":"Constructing a SinglePredicateEvaluator from a Predicate.SinglePredicate proto where hasInput() is false — e.g. a value_match or custom_match was configured but the input TypedExtensionConfig was omitted.","commonSituations":"xDS matcher configs where the input extension block is missing or renamed; config migration dropping the input field; hand-authored matcher trees that only specify the value condition.","solutions":["Set the input field (a TypedExtensionConfig identifying the MatchInput) on every SinglePredicate","Check proto.hasInput() during config validation before parsing the matcher tree","Update the management server/config template so input is always emitted alongside value_match/custom_match"],"exampleFix":"// before\nsingle_predicate:\n  value_match:\n    exact: my-header-value\n// after\nsingle_predicate:\n  input:\n    typed_config:\n      '@type': type.googleapis.com/grpc.xds.Input.MyHeaderInput\n  value_match:\n    exact: my-header-value","handlingStrategy":"validation","validationCode":"if (!singlePredicate.hasInput()) {\n  throw new IllegalArgumentException(\"single_predicate.input is required\");\n}","typeGuard":null,"tryCatchPattern":"try { new PredicateEvaluator.SinglePredicateEvaluator(proto); } catch (IllegalArgumentException e) { log.warn(\"Dropping predicate: \" + e.getMessage()); }","preventionTips":["Always emit the input TypedExtensionConfig alongside value_match/custom_match","Check hasInput() in config pre-validation","Keep input and match condition in the same config template block"],"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"}