{"record":{"id":"0172956587d716f1","repo":"hashicorp/nomad","slug":"retry-config-backoff-d-is-greater-than-default-ma","errorCode":null,"errorMessage":"retry config backoff %d is greater than default max_backoff %d","messagePattern":"retry config backoff (.+?) is greater than default max_backoff (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/config/config.go","lineNumber":848,"sourceCode":"}\n\n// Validate returns an error if the receiver is nil or empty, or if Backoff\n// is greater than  MaxBackoff.\nfunc (rc *RetryConfig) Validate() error {\n\t// If the config is nil or empty return false so that it is never assigned.\n\tif rc == nil || rc.IsEmpty() {\n\t\treturn errors.New(\"retry config is nil or empty\")\n\t}\n\n\t// If Backoff not set, no need to validate\n\tif rc.Backoff == nil {\n\t\treturn nil\n\t}\n\n\t// MaxBackoff nil will end up defaulted to 1 minutes. We should validate that\n\t// the user supplied backoff does not exceed that.\n\tif rc.MaxBackoff == nil && *rc.Backoff > config.DefaultRetryMaxBackoff {\n\t\treturn fmt.Errorf(\"retry config backoff %d is greater than default max_backoff %d\", *rc.Backoff, config.DefaultRetryMaxBackoff)\n\t}\n\n\t// MaxBackoff == 0 means backoff is unbounded. No need to validate.\n\tif rc.MaxBackoff != nil && *rc.MaxBackoff == 0 {\n\t\treturn nil\n\t}\n\n\tif rc.MaxBackoff != nil && *rc.Backoff > *rc.MaxBackoff {\n\t\treturn fmt.Errorf(\"retry config backoff %d is greater than max_backoff %d\", *rc.Backoff, *rc.MaxBackoff)\n\t}\n\n\treturn nil\n}\n\n// Merge merges two RetryConfigs. The passed instance always takes precedence.\nfunc (rc *RetryConfig) Merge(b *RetryConfig) *RetryConfig {\n\tif rc == nil {\n\t\treturn b","sourceCodeStart":830,"sourceCodeEnd":866,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/config/config.go#L830-L866","documentation":"RetryConfig.Validate ensures the retry backoff does not exceed the effective max backoff. When MaxBackoff is nil the library defaults max backoff to config.DefaultRetryMaxBackoff (1 minute), so a user-supplied Backoff larger than that default has no valid ceiling and validation fails with this message.","triggerScenarios":"Calling RetryConfig.Validate when Backoff is set (e.g. 120000000000 ns = 2m), MaxBackoff is nil, and *Backoff > config.DefaultRetryMaxBackoff, e.g. backoff=\"2m\" with no max_backoff in the config block.","commonSituations":"retry { backoff = ... } set to a value above 1m without also setting max_backoff in the agent config; copying a retry block that previously had max_backoff into a config where it was dropped; defaults changing between library versions so a formerly valid backoff now exceeds the default.","solutions":["Set max_backoff explicitly to a value >= backoff, e.g. backoff=\"2m\" max_backoff=\"5m\"","Lower backoff to at most the 1-minute default max (e.g. \"30s\") if unbounded growth is not desired","Review recent config/version changes that removed a previously present max_backoff"],"exampleFix":"// before\nretry {\n  backoff = \"2m\"\n}\n// after\nretry {\n  backoff = \"2m\"\n  max_backoff = \"5m\"\n}","handlingStrategy":"validation","validationCode":"const defaultMaxBackoff = time.Minute\nif rc.Backoff != nil && rc.MaxBackoff == nil && *rc.Backoff > defaultMaxBackoff {\n    return fmt.Errorf(\"backoff %s exceeds default max_backoff %s; set max_backoff\", *rc.Backoff, defaultMaxBackoff)\n}","typeGuard":"func backoffWithinDefaultMax(rc *config.RetryConfig, def time.Duration) bool {\n    return rc == nil || rc.Backoff == nil || (rc.MaxBackoff != nil) || *rc.Backoff <= def\n}","tryCatchPattern":"if err := rc.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"greater than default max_backoff\") {\n        rc.MaxBackoff = ptr(time.Duration(*rc.Backoff) * 2)\n        err = rc.Validate()\n    }\n    return err\n}","preventionTips":["Whenever backoff > 1m, always set max_backoff explicitly","Re-check retry blocks after upgrading, since default max may change","Validate merged configs, not just individual files"],"tags":["config","validation","retry","backoff","go"],"backgroundTag":"invalid-config-value","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}