hashicorp/nomad · error
retry config is nil or empty
Error message
retry config is nil or empty
What it means
This error comes from RetryConfig.Validate() in the client config package. It means the RetryConfig being validated is either nil or has no fields set (IsEmpty() returns true), so it is not a usable retry configuration and is rejected rather than being assigned/used. The library throws it to prevent silently running with a meaningless retry policy.
Source
Thrown at client/config/config.go:837
func (rc *RetryConfig) Equal(other *RetryConfig) bool {
return reflect.DeepEqual(rc, other)
}
// IsEmpty returns true if the receiver only contains an instance with no fields set.
func (rc *RetryConfig) IsEmpty() bool {
if rc == nil {
return true
}
return rc.Equal(&RetryConfig{})
}
// Validate returns an error if the receiver is nil or empty, or if Backoff
// is greater than MaxBackoff.
func (rc *RetryConfig) Validate() error {
// If the config is nil or empty return false so that it is never assigned.
if rc == nil || rc.IsEmpty() {
return errors.New("retry config is nil or empty")
}
// If Backoff not set, no need to validate
if rc.Backoff == nil {
return nil
}
// MaxBackoff nil will end up defaulted to 1 minutes. We should validate that
// the user supplied backoff does not exceed that.
if rc.MaxBackoff == nil && *rc.Backoff > config.DefaultRetryMaxBackoff {
return fmt.Errorf("retry config backoff %d is greater than default max_backoff %d", *rc.Backoff, config.DefaultRetryMaxBackoff)
}
// MaxBackoff == 0 means backoff is unbounded. No need to validate.
if rc.MaxBackoff != nil && *rc.MaxBackoff == 0 {
return nil
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Set at least one retry field (e.g. Attempts, Backoff/delay) on the RetryConfig before validating
- If retries are not wanted, remove the empty retry block or pass nil and skip assignment instead of validating an empty config
- Check that config decoding actually populated the retry section (look for typos in keys, wrong nesting, or wrong env var names)
Example fix
// before
rc := &RetryConfig{}
if err := rc.Validate(); err != nil { ... } // retry config is nil or empty
// after
rc := &RetryConfig{Attempts: 3, Backoff: 500 * time.Millisecond, MaxBackoff: 30 * time.Second}
if err := rc.Validate(); err != nil { ... } Defensive patterns
Strategy: validation
Validate before calling
func validRetry(rc *RetryConfig) bool { return rc != nil && !rc.IsEmpty() } Type guard
if rc == nil || rc.IsEmpty() {
// treat as "no retry config": skip assignment or substitute defaults
} Try / catch
if err := rc.Validate(); err != nil {
log.Printf("retry config invalid: %v; using defaults", err)
rc = defaultRetryConfig
} Prevention
- Always construct RetryConfig with at least Backoff/Attempts set before validating
- Use a helper/constructor that fills defaults instead of zero-valued structs
- Add a config-load test asserting the retry section decodes non-empty
- Skip assignment (per the comment in Validate) rather than storing an empty config
When it happens
Trigger: Calling RetryConfig.Validate() on a nil *RetryConfig, or on a zero-valued RetryConfig{} (e.g. constructed via var rc RetryConfig or &RetryConfig{} without setting any fields) during config validation.
Common situations: Hand-written client/HCL/JSON config where a retry block exists but is empty; programmatically building a RetryConfig but forgetting to set Backoff or interval fields; config decoding that yields a non-nil struct with all zero values.
Related errors
- retry config backoff %d is greater than default max_backoff
- retry config backoff %d is greater than max_backoff %d
- wait config is nil or empty
- fingerprint name cannot be empty
- rcp.accept_backlog interval must be greater than zero
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f5448466483ac055.
Report an issue: GitHub.