{"record":{"id":"9e89d740edf4d7fa","repo":"hashicorp/terraform","slug":"can-t-compute-sum-of-opposing-infinities","errorCode":null,"errorMessage":"can't compute sum of opposing infinities","messagePattern":"can't compute sum of opposing infinities","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lang/funcs/collection.go","lineNumber":532,"sourceCode":"\t\targ := args[0].AsValueSlice()\n\t\tty := args[0].Type()\n\n\t\tif !ty.IsListType() && !ty.IsSetType() && !ty.IsTupleType() {\n\t\t\treturn cty.NilVal, function.NewArgErrorf(0, \"argument must be list, set, or tuple. Received %s\", ty.FriendlyName())\n\t\t}\n\n\t\tif !args[0].IsWhollyKnown() {\n\t\t\treturn cty.UnknownVal(cty.Number), nil\n\t\t}\n\n\t\t// big.Float.Add can panic if the input values are opposing infinities,\n\t\t// so we must catch that here in order to remain within\n\t\t// the cty Function abstraction.\n\t\tdefer func() {\n\t\t\tif r := recover(); r != nil {\n\t\t\t\tif _, ok := r.(big.ErrNaN); ok {\n\t\t\t\t\tret = cty.NilVal\n\t\t\t\t\terr = fmt.Errorf(\"can't compute sum of opposing infinities\")\n\t\t\t\t} else {\n\t\t\t\t\t// not a panic we recognize\n\t\t\t\t\tpanic(r)\n\t\t\t\t}\n\t\t\t}\n\t\t}()\n\n\t\ts := arg[0]\n\t\tif s.IsNull() {\n\t\t\treturn cty.NilVal, function.NewArgErrorf(0, \"argument must be list, set, or tuple of number values\")\n\t\t}\n\t\ts, err = convert.Convert(s, cty.Number)\n\t\tif err != nil {\n\t\t\treturn cty.NilVal, function.NewArgErrorf(0, \"argument must be list, set, or tuple of number values\")\n\t\t}\n\t\tfor _, v := range arg[1:] {\n\t\t\tif v.IsNull() {\n\t\t\t\treturn cty.NilVal, function.NewArgErrorf(0, \"argument must be list, set, or tuple of number values\")","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/lang/funcs/collection.go#L514-L550","documentation":"Thrown by the `sum()` collection function (SumFunc) when the underlying big.Float arithmetic panics with big.ErrNaN, which math/big raises when adding opposing-signed infinities (+Inf and -Inf). A deferred recover() in the implementation catches the panic and converts it into this clean error so the panic never escapes the cty function abstraction. It is a genuine user-facing error: summing a list that contains both positive and negative infinity is mathematically undefined.","triggerScenarios":"Calling `sum([...])` in HCL where the list contains values whose magnitudes overflow cty.Number to +Inf and -Inf, or a provider emits explicit infinite values of opposite signs. For example `sum([1e400 * 1e400, -1e400 * 1e400])` where both operands overflow to opposing infinities, or `sum([1/0, -1/0])`.","commonSituations":"Aggregating provider-computed numeric fields that occasionally divide by zero or overflow; summing monetary/resource counters that become unbounded; mixing legacy values that degraded to infinities during provider upgrades.","solutions":["Filter out non-finite values before summing, e.g. `sum([for v in var.nums : v if v == v && v != floor(v) - floor(v)])` or a `compact`/guard to drop infinities.","Clamp or bound the source values so they never reach +/-Inf (cap divisors away from zero, cap exponents).","If one infinity is expected, replace `sum()` with explicit conditional logic that handles the infinite case.","Check the producing provider/resource for an overflow bug that emits Infinity where a finite value was intended."],"exampleFix":"// before\nlocals {\n  total = sum(var.quotients)\n}\n\n// after: drop non-finite values before summing\nlocals {\n  finite = [for q in var.quotients : q if can(q * 0 == 0) && q != signum(q) * 1e308 * 1e308]\n  total  = length(local.finite) > 0 ? sum(local.finite) : null\n}","handlingStrategy":"validation","validationCode":"// HCL: filter out non-finite values before sum()\nlocals {\n  nums = [for v in var.values : v if can(v == 0) && !(v > 1e308 * 1e308) && !(v < -1e308 * 1e308)]\n  total = length(local.nums) > 0 ? sum(local.nums) : 0\n}","typeGuard":"// HCL guard: detect mixed-sign infinities that would conflict\nlocals {\n  has_pos_inf = anytrue([for v in var.values : v > 1e308 * 1e308])\n  has_neg_inf = anytrue([for v in var.values : v < -1e308 * 1e308])\n  safe        = !(local.has_pos_inf && local.has_neg_inf)\n}","tryCatchPattern":null,"preventionTips":["Sanitize provider outputs that may divide by zero or overflow before summing.","Clamp divisors away from zero and cap exponents in computed numerics.","Validate numeric inputs with `can()` guards in HCL before aggregation."],"tags":["terraform","hcl","sum-func","math","overflow","cty"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}