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

  1. Set at least one retry field (e.g. Attempts, Backoff/delay) on the RetryConfig before validating
  2. If retries are not wanted, remove the empty retry block or pass nil and skip assignment instead of validating an empty config
  3. 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

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/f5448466483ac055. Report an issue: GitHub.