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

  1. Provide an integer value for the attribute.
  2. If a fractional input is legitimate upstream, floor/round it before passing to IntValue and document the rounding.
  3. Validate with a check like v.AsBigFloat().Int64() accuracy before calling IntValue to give a clearer message.
  4. 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

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


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)