{"record":{"id":"47b9baef79d5059b","repo":"grpc/grpc-java","slug":"invalid-duration-in-weighted-round-robin-config","errorCode":null,"errorMessage":"Invalid duration in weighted round robin config: \" + ex.getMessage()","messagePattern":"Invalid duration in weighted round robin config: \" \\+ ex\\.getMessage\\(\\)","errorType":"validation","errorClass":"ResourceInvalidException","httpStatus":null,"severity":"error","filePath":"xds/src/main/java/io/grpc/xds/LoadBalancerConfigFactory.java","lineNumber":302,"sourceCode":"      return buildRingHashConfig(\n          ringHash.hasMinimumRingSize() ? ringHash.getMinimumRingSize().getValue() : null,\n          ringHash.hasMaximumRingSize() ? ringHash.getMaximumRingSize().getValue() : null);\n    }\n\n    private static ImmutableMap<String, ?> convertWeightedRoundRobinConfig(\n        ClientSideWeightedRoundRobin wrr) throws ResourceInvalidException {\n      try {\n        return buildWrrConfig(\n            wrr.hasBlackoutPeriod() ? Durations.toString(wrr.getBlackoutPeriod()) : null,\n            wrr.hasWeightExpirationPeriod()\n                ? Durations.toString(wrr.getWeightExpirationPeriod()) : null,\n            wrr.hasOobReportingPeriod() ? Durations.toString(wrr.getOobReportingPeriod()) : null,\n            wrr.hasEnableOobLoadReport() ? wrr.getEnableOobLoadReport().getValue() : null,\n            wrr.hasWeightUpdatePeriod() ? Durations.toString(wrr.getWeightUpdatePeriod()) : null,\n            wrr.hasErrorUtilizationPenalty() ? wrr.getErrorUtilizationPenalty().getValue() : null,\n            ImmutableList.copyOf(wrr.getMetricNamesForComputingUtilizationList()));\n      } catch (IllegalArgumentException ex) {\n        throw new ResourceInvalidException(\"Invalid duration in weighted round robin config: \"\n            + ex.getMessage());\n      }\n    }\n\n    /**\n     * Converts a wrr_locality {@link Any} configuration to service config format.\n     */\n    private static ImmutableMap<String, ?> convertWrrLocalityConfig(WrrLocality wrrLocality,\n        int recursionDepth)\n        throws ResourceInvalidException, MaxRecursionReachedException {\n      return buildWrrLocalityConfig(\n          convertToServiceConfig(wrrLocality.getEndpointPickingPolicy(), recursionDepth + 1));\n    }\n\n    /**\n     * \"Converts\" a round_robin configuration to service config format.\n     */\n    private static ImmutableMap<String, ?> convertRoundRobinConfig() {","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/xds/src/main/java/io/grpc/xds/LoadBalancerConfigFactory.java#L284-L320","documentation":"A duration field in the weighted round robin (WRR) localities config (e.g. oob_reporting_period or weight_update_period) failed proto-to-JSON duration conversion (Durations.toString / buildWeightedRoundRobinConfig), meaning the control plane sent an invalid duration value. The factory wraps that IllegalArgumentException into a ResourceInvalidException so the xDS resource is rejected.","triggerScenarios":"convertWeightedRoundRobinConfig calls buildWeightedRoundRobinConfig with the WRR proto's duration fields; any of them being malformed or out of allowed range throws IllegalArgumentException from the duration conversion/builder, which is rethrown with this message.","commonSituations":"A custom xDS management server emitting a zero/negative or unrepresentable weight_update_period; proto JSON with a missing unit in a duration string; typo'd duration in a WrrLocality config in an Istio/Envoy patch.","solutions":["Fix the duration fields (oob_reporting_period, weight_update_period) in the WRR localities config on the control plane to valid protobuf Durations (e.g. \"10s\", \"0.5s\")","Check the cause message (appended after the colon) to see which exact value was rejected","Validate the config with Envoy's config dump or protoc validation before pushing it via ADS","Remove the optional duration field entirely if a default is acceptable"],"exampleFix":"# before (WRR localities config)\noob_reporting_period: \"ten seconds\"\n# after\noob_reporting_period: \"10s\"","handlingStrategy":"validation","validationCode":"// Validate WRR durations are positive before shipping the config:\nif (wrr.hasWeightUpdatePeriod()\n    && com.google.protobuf.util.Durations.toMillis(wrr.getWeightUpdatePeriod().getValue()) <= 0) {\n  throw new IllegalArgumentException(\"weight_update_period must be > 0\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  serviceConfig = convertWeightedRoundRobinConfig(wrr);\n} catch (ResourceInvalidException e) {\n  // message carries the original IllegalArgumentException text\n  logger.warning(\"Bad WRR config: \" + e.getMessage());\n  serviceConfig = defaultRoundRobinConfig();\n}","preventionTips":["Emit durations in canonical protobuf form (\"10s\", \"0.5s\")","Never emit zero or negative periods","Test control-plane config changes against a grpc-xds client before rollout"],"tags":["grpc","xds","load-balancing","weighted-round-robin","duration"],"backgroundTag":"invalid-duration-format","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"}