hashicorp/terraform · error
IPv6 addresses cannot have a netmask
Error message
IPv6 addresses cannot have a netmask: %s
What it means
cidrnetmask() error specific to IPv6: cidrnetmask is defined only for IPv4 (which uses dotted-decimal masks). When the parsed CIDR is IPv6 (network.IP.To4() == nil), the function refuses to compute a netmask because IPv6 uses CIDR length notation only and has no equivalent dotted mask.
Solutions
- For IPv6 use the prefix length directly (e.g. split on '/' to get /32) instead of cidrnetmask.
- Branch on family: check the address contains ':' before calling cidrnetmask.
- Constrain the variable validation to IPv4 CIDRs if cidrnetmask is required.
Example fix
// before
locals { mask = cidrnetmask(var.cidr) } # fails for IPv6
// after
locals { mask = var.cidr == "" ? null : (can(regex(":", var.cidr)) ? split("/", var.cidr)[1] : cidrnetmask(var.cidr)) } Defensive patterns
Strategy: validation
Validate before calling
// Branch on address family before calling cidrnetmask.
locals {
is_v6 = can(regex(":", var.cidr))
mask = local.is_v6 ? split("/", var.cidr)[1] : cidrnetmask(var.cidr)
} Prevention
- Never call cidrnetmask on an IPv6 CIDR; use the prefix length.
- For dual-stack variables, branch on the presence of ':'.
- Constrain variables to IPv4 when cidrnetmask is required.
When it happens
Trigger: Calling cidrnetmask("2001:db8::/32") or any IPv6 CIDR; To4() returns nil and the function returns this error including the offending prefix.
Common situations: Variable that can be either IPv4 or IPv6 family (dual-stack configs), a recently migrated network from v4 to v6, or a module that hard-codes cidrnetmask over a generic cidr variable.
Related errors
- invalid CIDR expression
- can't compute sum of opposing infinities
- invalid collection length
- lookup failed to find key
- lookup() takes two or three arguments, got
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/c29ae70e1ba84f48.
Report an issue: GitHub.
Appendix: source
Thrown at internal/lang/funcs/cidr.go:70
// CidrNetmaskFunc contructs a function that converts an IPv4 address prefix given
// in CIDR notation into a subnet mask address.
var CidrNetmaskFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "prefix",
Type: cty.String,
},
},
Type: function.StaticReturnType(cty.String),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
_, network, err := ipaddr.ParseCIDR(args[0].AsString())
if err != nil {
return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %s", err)
}
if network.IP.To4() == nil {
return cty.UnknownVal(cty.String), fmt.Errorf("IPv6 addresses cannot have a netmask: %s", args[0].AsString())
}
return cty.StringVal(ipaddr.IP(network.Mask).String()), nil
},
})
// CidrSubnetFunc contructs a function that calculates a subnet address within
// a given IP network address prefix.
var CidrSubnetFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "prefix",
Type: cty.String,
},
{
Name: "newbits",
Type: cty.Number,
},View on GitHub (pinned to d32a084675)