{"record":{"id":"c29ae70e1ba84f48","repo":"hashicorp/terraform","slug":"ipv6-addresses-cannot-have-a-netmask-s","errorCode":null,"errorMessage":"IPv6 addresses cannot have a netmask: %s","messagePattern":"IPv6 addresses cannot have a netmask: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lang/funcs/cidr.go","lineNumber":70,"sourceCode":"// CidrNetmaskFunc contructs a function that converts an IPv4 address prefix given\n// in CIDR notation into a subnet mask address.\nvar CidrNetmaskFunc = function.New(&function.Spec{\n\tParams: []function.Parameter{\n\t\t{\n\t\t\tName: \"prefix\",\n\t\t\tType: cty.String,\n\t\t},\n\t},\n\tType:         function.StaticReturnType(cty.String),\n\tRefineResult: refineNotNull,\n\tImpl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {\n\t\t_, network, err := ipaddr.ParseCIDR(args[0].AsString())\n\t\tif err != nil {\n\t\t\treturn cty.UnknownVal(cty.String), fmt.Errorf(\"invalid CIDR expression: %s\", err)\n\t\t}\n\n\t\tif network.IP.To4() == nil {\n\t\t\treturn cty.UnknownVal(cty.String), fmt.Errorf(\"IPv6 addresses cannot have a netmask: %s\", args[0].AsString())\n\t\t}\n\n\t\treturn cty.StringVal(ipaddr.IP(network.Mask).String()), nil\n\t},\n})\n\n// CidrSubnetFunc contructs a function that calculates a subnet address within\n// a given IP network address prefix.\nvar CidrSubnetFunc = function.New(&function.Spec{\n\tParams: []function.Parameter{\n\t\t{\n\t\t\tName: \"prefix\",\n\t\t\tType: cty.String,\n\t\t},\n\t\t{\n\t\t\tName: \"newbits\",\n\t\t\tType: cty.Number,\n\t\t},","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/lang/funcs/cidr.go#L52-L88","documentation":"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.","triggerScenarios":"Calling cidrnetmask(\"2001:db8::/32\") or any IPv6 CIDR; To4() returns nil and the function returns this error including the offending prefix.","commonSituations":"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.","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."],"exampleFix":"// before\nlocals { mask = cidrnetmask(var.cidr) } # fails for IPv6\n\n// after\nlocals { mask = var.cidr == \"\" ? null : (can(regex(\":\", var.cidr)) ? split(\"/\", var.cidr)[1] : cidrnetmask(var.cidr)) }","handlingStrategy":"validation","validationCode":"// Branch on address family before calling cidrnetmask.\nlocals {\n  is_v6 = can(regex(\":\", var.cidr))\n  mask  = local.is_v6 ? split(\"/\", var.cidr)[1] : cidrnetmask(var.cidr)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["terraform","hcl-functions","cidr","ipv6","networking"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}