{"record":{"id":"3a9a0b3c164290b0","repo":"grpc/grpc-go","slug":"outlierdetectionloadbalancingconfig-max-ejection-t","errorCode":null,"errorMessage":"OutlierDetectionLoadBalancingConfig.max_ejection_time = %s; must be >= 0","messagePattern":"OutlierDetectionLoadBalancingConfig\\.max_ejection_time = (.+?); must be >= 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/xds/balancer/outlierdetection/balancer.go","lineNumber":135,"sourceCode":"\t// resource before parsing resource into JSON which this function gets\n\t// called with. A50 defines two separate places for these validations to\n\t// take place, the xdsclient and this ParseConfig method. \"When parsing a\n\t// config from JSON, if any of these requirements is violated, that should\n\t// be treated as a parsing error.\" - A50\n\tswitch {\n\t// \"The google.protobuf.Duration fields interval, base_ejection_time, and\n\t// max_ejection_time must obey the restrictions in the\n\t// google.protobuf.Duration documentation and they must have non-negative\n\t// values.\" - A50\n\t// Approximately 290 years is the maximum time that time.Duration (int64)\n\t// can represent. The restrictions on the protobuf.Duration field are to be\n\t// within +-10000 years. Thus, just check for negative values.\n\tcase lbCfg.Interval < 0:\n\t\treturn nil, fmt.Errorf(\"OutlierDetectionLoadBalancingConfig.interval = %s; must be >= 0\", lbCfg.Interval)\n\tcase lbCfg.BaseEjectionTime < 0:\n\t\treturn nil, fmt.Errorf(\"OutlierDetectionLoadBalancingConfig.base_ejection_time = %s; must be >= 0\", lbCfg.BaseEjectionTime)\n\tcase lbCfg.MaxEjectionTime < 0:\n\t\treturn nil, fmt.Errorf(\"OutlierDetectionLoadBalancingConfig.max_ejection_time = %s; must be >= 0\", lbCfg.MaxEjectionTime)\n\n\t// \"The fields max_ejection_percent,\n\t// success_rate_ejection.enforcement_percentage,\n\t// failure_percentage_ejection.threshold, and\n\t// failure_percentage.enforcement_percentage must have values less than or\n\t// equal to 100.\" - A50\n\tcase lbCfg.MaxEjectionPercent > 100:\n\t\treturn nil, fmt.Errorf(\"OutlierDetectionLoadBalancingConfig.max_ejection_percent = %v; must be <= 100\", lbCfg.MaxEjectionPercent)\n\tcase lbCfg.SuccessRateEjection != nil && lbCfg.SuccessRateEjection.EnforcementPercentage > 100:\n\t\treturn nil, fmt.Errorf(\"OutlierDetectionLoadBalancingConfig.SuccessRateEjection.enforcement_percentage = %v; must be <= 100\", lbCfg.SuccessRateEjection.EnforcementPercentage)\n\tcase lbCfg.FailurePercentageEjection != nil && lbCfg.FailurePercentageEjection.Threshold > 100:\n\t\treturn nil, fmt.Errorf(\"OutlierDetectionLoadBalancingConfig.FailurePercentageEjection.threshold = %v; must be <= 100\", lbCfg.FailurePercentageEjection.Threshold)\n\tcase lbCfg.FailurePercentageEjection != nil && lbCfg.FailurePercentageEjection.EnforcementPercentage > 100:\n\t\treturn nil, fmt.Errorf(\"OutlierDetectionLoadBalancingConfig.FailurePercentageEjection.enforcement_percentage = %v; must be <= 100\", lbCfg.FailurePercentageEjection.EnforcementPercentage)\n\t}\n\treturn lbCfg, nil\n}\n","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/xds/balancer/outlierdetection/balancer.go#L117-L153","documentation":"Per gRFC A50, OutlierDetectionLoadBalancingConfig.max_ejection_time must be a non-negative duration. ParseConfig checks lbCfg.MaxEjectionTime < 0 and rejects it (balancer.go:134-135). Unreachable in normal xDS flow due to upstream xdsclient validation.","triggerScenarios":"lbCfg.MaxEjectionTime is negative after JSON unmarshaling (e.g. \"max_ejection_time\": \"-300s\").","commonSituations":"Hand-crafted config with a negative duration; typo; control plane misconfiguration that bypassed xdsclient validation.","solutions":["Set max_ejection_time to a non-negative value (A50 default is 300s).","Validate the duration before constructing the config."],"exampleFix":"// before\ncfg.MaxEjectionTime = iserviceconfig.Duration(-300 * time.Second)\n// after\ncfg.MaxEjectionTime = iserviceconfig.Duration(300 * time.Second)","handlingStrategy":"validation","validationCode":"func validateMaxEjectionTime(d iserviceconfig.Duration) error {\n    if d < 0 { return fmt.Errorf(\"max_ejection_time must be >= 0, got %s\", d) }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default MaxEjectionTime to 300s per A50.","Range-check every duration field before building the LBConfig.","Treat negative durations as a deployment-time config error."],"tags":["go","grpc","xds","outlier-detection","validation","duration"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}