hashicorp/terraform · error

must not be null

Error message

must not be null

What it means

Returned by backendbase.IntValue when the cty.Value, after successful conversion to cty.Number, is null. The function expects a non-null number it can convert to int64; a null value fails at helper.go:105-107. (Note: a value that fails convert.Convert to Number returns a different, conversion-specific error earlier.)

Solutions

  1. Substitute a non-null default with GetPathDefault / GetAttrEnvDefaultFallback before calling IntValue.
  2. Check v.IsNull() yourself and skip or use a default instead of calling IntValue.
  3. Make the backend schema attribute Required so Terraform rejects null at config-load time.
  4. If null is a legitimate 'unset', branch on it rather than forcing conversion.

Example fix

// before
n, err := backendbase.IntValue(cfg.GetAttr("port"))

// after
portVal := backendbase.GetAttrEnvDefaultFallback(cfg, "port", "TF_BACKEND_PORT", cty.NumberIntVal(8080))
n, err := backendbase.IntValue(portVal)
Defensive patterns

Strategy: validation

Validate before calling

// Apply a default before calling IntValue
portVal := backendbase.GetAttrEnvDefaultFallback(cfg, "port", "TF_PORT", cty.NumberIntVal(8080))
if portVal.IsNull() {
    return errors.New("port is required")
}

Type guard

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

Try / catch

if cfg.GetAttr("port").IsNull() {
    return errors.New("port must be set")
}
n, err := backendbase.IntValue(cfg.GetAttr("port"))

Prevention

When it happens

Trigger: Calling IntValue on a backend config attribute that was declared but not set (null) — e.g. an optional numeric backend attribute the user omitted.

Common situations: Backend config attribute is optional and the user did not provide it; upstream code did not apply GetPathDefault/GetPathEnvDefaultFallback to substitute a non-null default before calling IntValue; the value came from a variable resolving to null.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/5a15accb16230621. Report an issue: GitHub.

Appendix: source

Thrown at internal/backend/backendbase/helper.go:106

// Unless the fallback value is null itself, this function guarantees to never
// return null.
func GetAttrEnvDefaultFallback(v cty.Value, attrName string, defEnv string, fallback cty.Value) cty.Value {
	ret := GetAttrEnvDefault(v, attrName, defEnv)
	if ret.IsNull() {
		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")

View on GitHub (pinned to d32a084675)