hashicorp/terraform · error
must not be a whole number
Error message
must not be a whole number
What it means
Returned by backendbase.IntValue when the cty.Number value is non-null but its big.Float does not convert to int64 exactly (big.Accuracy != big.Exact). In other words the user supplied a fractional number where the backend schema requires a whole number.
Source
Thrown at internal/backend/backendbase/helper.go:111
return fallback
}
return ret
}
// IntValue converts a cty value into a Go int64, or returns an error if that's
// not possible.
func IntValue(v cty.Value) (int64, error) {
v, err := convert.Convert(v, cty.Number)
if err != nil {
return 0, err
}
if v.IsNull() {
return 0, fmt.Errorf("must not be null")
}
bf := v.AsBigFloat()
ret, acc := bf.Int64()
if acc != big.Exact {
return 0, fmt.Errorf("must not be a whole number")
}
return ret, nil
}
// BoolValue converts a cty value Go bool, or returns an error if that's not
// possible.
func BoolValue(v cty.Value) (bool, error) {
v, err := convert.Convert(v, cty.Bool)
if err != nil {
return false, err
}
if v.IsNull() {
return false, fmt.Errorf("must not be null")
}
return v.True(), nil
}
// MustBoolValue converts a cty value Go bool, or panics if that's not possible.View on GitHub (pinned to c9def3e214)
Solutions
- Change the value to a whole number: `retry_wait_max = 3`.
- If sub-second precision is needed, check whether the backend supports a finer unit; otherwise round up/down to the nearest integer.
- Review the backend's documented schema to confirm the attribute is an integer.
- Validate user-supplied config with a 'must be integer' check before init.
Example fix
// before (fractional -> 'must not be a whole number')
backend "http" {
address = "https://state.example.com"
retry_wait_max = 2.5
}
// after
backend "http" {
address = "https://state.example.com"
retry_wait_max = 3
} Defensive patterns
Strategy: validation
Validate before calling
// Reject fractional numbers before IntValue.
if v.Type() == cty.Number {
bf := v.AsBigFloat()
if _, acc := bf.Int64(); acc != big.Exact {
return errors.New("value must be a whole number")
}
} Type guard
func isNonIntegerError(err error) bool {
return err != nil && err.Error() == "must not be a whole number"
} Try / catch
n, err := backendbase.IntValue(v)
if err != nil {
// surface with the attribute name for clarity
return fmt.Errorf("%s: %w", attrName, err)
} Prevention
- Use whole numbers for integer backend fields.
- Round/ceil programmatically before config if needed.
- Validate config int-ness before init.
When it happens
Trigger: Returned at internal/backend/backendbase/helper.go:111 when bf.Int64() returns acc != big.Exact. Used by the http backend for retry_max / retry_wait_min / retry_wait_max (and any backend calling IntValue for an int field).
Common situations: Setting `retry_wait_max = 2.5` (seconds) or any decimal where the backend expects an integer count/seconds. Misreading a duration field that actually wants whole seconds. Copy-pasting a float default from docs.
Related errors
- must not be null
- attribute %q is required
- configuration file did not contain profile: %s
- expected type of %s to be int
- expected %s to be in the range (%d - %d), got %d
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/901a891d1bebf846.
Report an issue: GitHub.