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 (non-null, number-convertible) cty.Value cannot be converted to int64 exactly — i.e. big.Float.Int64 returns an accuracy other than big.Exact, meaning the value has a fractional component (e.g. 3.5). IMPORTANT: the message text 'must not be a whole number' is inverted/misleading — the function actually requires the value TO BE a whole number; the error fires precisely because it is NOT one. Treat this as 'value must be a whole number'.
Solutions
- Provide an integer value for the attribute.
- If a fractional input is legitimate upstream, floor/round it before passing to IntValue and document the rounding.
- Validate with a check like v.AsBigFloat().Int64() accuracy before calling IntValue to give a clearer message.
- Report the misleading error text upstream — the message should read 'must be a whole number'.
Example fix
// before — user supplies port = 8080.5
n, err := backendbase.IntValue(cfg.GetAttr("port")) // err: "must not be a whole number"
// after — enforce integer at the schema/config layer
// port = 8080 (HCL)
// or, defensively:
bf := portVal.AsBigFloat()
if _, acc := bf.Int64(); acc != big.Exact {
return fmt.Errorf("port must be an integer, got %s", bf.Text('f', -1))
}
n, err := backendbase.IntValue(portVal) Defensive patterns
Strategy: validation
Validate before calling
// Verify the value is a whole number before converting
bf := v.AsBigFloat()
if _, acc := bf.Int64(); acc != big.Exact {
return fmt.Errorf("value must be an integer, got %s", bf.Text('f', -1))
} Type guard
func isWholeNumber(v cty.Value) bool {
if v.IsNull() || v.Type() != cty.Number {
return false
}
_, acc := v.AsBigFloat().Int64()
return acc == big.Exact
} Try / catch
if !isWholeNumber(v) {
return fmt.Errorf("value must be a whole number")
}
n, err := backendbase.IntValue(v)
// NOTE: the library's own message is inverted; treat it as 'must be a whole number'. Prevention
- Reject fractional inputs at the schema/config boundary with integer constraints.
- Floor/round deliberately only when a fractional value is semantically acceptable.
- Remember the library message is misleading: it fires when the value is NOT a whole number.
When it happens
Trigger: IntValue at helper.go:108-112: after converting to Number and confirming non-null, it calls bf.Int64(); if acc != big.Exact (fractional part present) it returns this error.
Common situations: A user supplies a fractional value (e.g. port=8080.5, retries=2.3) to a backend attribute that must be an integer; a computed/interpolated expression yields a non-integer; unit conversion producing a float.
Related errors
- must not be null
- Can't serialize backend configuration as JSON
- cannot decode tfvars from a null value
- confirmFunc must not be nil
- could not decode output
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/901a891d1bebf846.
Report an issue: GitHub.
Appendix: 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 d32a084675)