{"record":{"id":"901a891d1bebf846","repo":"hashicorp/terraform","slug":"must-not-be-a-whole-number","errorCode":null,"errorMessage":"must not be a whole number","messagePattern":"must not be a whole number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/backendbase/helper.go","lineNumber":111,"sourceCode":"\t\treturn fallback\n\t}\n\treturn ret\n}\n\n// IntValue converts a cty value into a Go int64, or returns an error if that's\n// not possible.\nfunc IntValue(v cty.Value) (int64, error) {\n\tv, err := convert.Convert(v, cty.Number)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tif v.IsNull() {\n\t\treturn 0, fmt.Errorf(\"must not be null\")\n\t}\n\tbf := v.AsBigFloat()\n\tret, acc := bf.Int64()\n\tif acc != big.Exact {\n\t\treturn 0, fmt.Errorf(\"must not be a whole number\")\n\t}\n\treturn ret, nil\n}\n\n// BoolValue converts a cty value Go bool, or returns an error if that's not\n// possible.\nfunc BoolValue(v cty.Value) (bool, error) {\n\tv, err := convert.Convert(v, cty.Bool)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tif v.IsNull() {\n\t\treturn false, fmt.Errorf(\"must not be null\")\n\t}\n\treturn v.True(), nil\n}\n\n// MustBoolValue converts a cty value Go bool, or panics if that's not possible.","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/backendbase/helper.go#L93-L129","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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'."],"exampleFix":"// before — user supplies port = 8080.5\nn, err := backendbase.IntValue(cfg.GetAttr(\"port\")) // err: \"must not be a whole number\"\n\n// after — enforce integer at the schema/config layer\n// port = 8080  (HCL) \n// or, defensively:\nbf := portVal.AsBigFloat()\nif _, acc := bf.Int64(); acc != big.Exact {\n    return fmt.Errorf(\"port must be an integer, got %s\", bf.Text('f', -1))\n}\nn, err := backendbase.IntValue(portVal)","handlingStrategy":"validation","validationCode":"// Verify the value is a whole number before converting\nbf := v.AsBigFloat()\nif _, acc := bf.Int64(); acc != big.Exact {\n    return fmt.Errorf(\"value must be an integer, got %s\", bf.Text('f', -1))\n}","typeGuard":"func isWholeNumber(v cty.Value) bool {\n    if v.IsNull() || v.Type() != cty.Number {\n        return false\n    }\n    _, acc := v.AsBigFloat().Int64()\n    return acc == big.Exact\n}","tryCatchPattern":"if !isWholeNumber(v) {\n    return fmt.Errorf(\"value must be a whole number\")\n}\nn, err := backendbase.IntValue(v)\n// NOTE: the library's own message is inverted; treat it as 'must be a whole number'.","preventionTips":["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."],"tags":["backend","cty","integer-validation","misleading-message","terraform"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}