hashicorp/terraform · error

invalid retry_max: %s

Error message

invalid retry_max: %s

What it means

Configure calls backendbase.IntValue on the retry_max attribute (default 2, env TF_HTTP_RETRY_MAX). If the supplied cty.Number cannot be converted to an int — e.g. it is a fractional float, out-of-range, or not a number at all — IntValue returns an error which is wrapped here. retry_max controls how many times go-retryablehttp retries a failed request.

Source

Thrown at internal/backend/remote-state/http/backend.go:195

			return backendbase.ErrorAsDiagnostics(
				fmt.Errorf("unlock_address must be HTTP or HTTPS"),
			)
		}
	}
	unlockMethod := backendbase.GetAttrEnvDefaultFallback(
		configVal, "unlock_method",
		"TF_HTTP_UNLOCK_METHOD", cty.StringVal("UNLOCK"),
	).AsString()

	retryMax, err := backendbase.IntValue(
		backendbase.GetAttrEnvDefaultFallback(
			configVal, "retry_max",
			"TF_HTTP_RETRY_MAX", cty.NumberIntVal(2),
		),
	)
	if err != nil {
		return backendbase.ErrorAsDiagnostics(
			fmt.Errorf("invalid retry_max: %s", err),
		)
	}
	retryWaitMin, err := backendbase.IntValue(
		backendbase.GetAttrEnvDefaultFallback(
			configVal, "retry_wait_min",
			"TF_HTTP_RETRY_WAIT_MIN", cty.NumberIntVal(1),
		),
	)
	if err != nil {
		return backendbase.ErrorAsDiagnostics(
			fmt.Errorf("invalid retry_wait_min: %s", err),
		)
	}
	retryWaitMax, err := backendbase.IntValue(
		backendbase.GetAttrEnvDefaultFallback(
			configVal, "retry_wait_max",
			"TF_HTTP_RETRY_WAIT_MAX", cty.NumberIntVal(30),
		),

View on GitHub (pinned to c9def3e214)

Solutions

  1. Set retry_max to a whole, non-negative integer (e.g. retry_max = 2).
  2. Remove the line to accept the default of 2.
  3. If set via TF_HTTP_RETRY_MAX, ensure the env value is a plain integer string with no decimal point.

Example fix

// before
retry_max = 2.5
// after
retry_max = 2
Defensive patterns

Strategy: validation

Validate before calling

// Ensure retry_max is an integer before terraform init
func validateRetryMax(v interface{}) error {
  n, ok := v.(int)
  if !ok { return fmt.Errorf("retry_max must be int, got %T", v) }
  if n < 0 { return fmt.Errorf("retry_max must be >= 0") }
  return nil
}

Type guard

func isRetryInt(v cty.Value) bool {
  return v.Type() == cty.Number && !v.IsNull() && v.AsBigFloat().IsInt()
}

Prevention

When it happens

Trigger: Setting retry_max to a non-integer number like 2.5, a huge value overflowing int, or feeding a value that HCL evaluates as a non-number. Triggered at backend Configure time.

Common situations: Operator writes retry_max = 2.5 thinking fractional retries are allowed; passes a string "3" expecting coercion; CI template injects a float from a YAML config.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/489f75a320d8edc3. Report an issue: GitHub.