hashicorp/terraform · error
invalid CIDR expression: %s
Error message
invalid CIDR expression: %s
What it means
Returned by the cidrhost built-in (CidrHostFunc, internal/lang/funcs/cidr.go:40) when ipaddr.ParseCIDR(args[0].AsString()) fails for the prefix argument. ParseCIDR requires true CIDR notation (address/prefixlen, e.g. 10.0.0.0/16); a bare IP, a host with a host portion set, or a malformed string all fail and the error is surfaced verbatim as the second %s.
Source
Thrown at internal/lang/funcs/cidr.go:40
{
Name: "prefix",
Type: cty.String,
},
{
Name: "hostnum",
Type: cty.Number,
},
},
Type: function.StaticReturnType(cty.String),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
var hostNum *big.Int
if err := gocty.FromCtyValue(args[1], &hostNum); err != nil {
return cty.UnknownVal(cty.String), err
}
_, network, err := ipaddr.ParseCIDR(args[0].AsString())
if err != nil {
return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %s", err)
}
ip, err := cidr.HostBig(network, hostNum)
if err != nil {
return cty.UnknownVal(cty.String), err
}
return cty.StringVal(ip.String()), nil
},
})
// 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,View on GitHub (pinned to c9def3e214)
Solutions
- Provide the prefix with an explicit mask: cidrhost("10.0.0.0/16", 5).
- If the prefix is computed, ensure it always carries a /mask before being passed to cidrhost.
- Guard null/unknown: only call cidrhost when the prefix var is known and non-empty.
- Use cidrsubnet/cidrsubnets to derive valid network prefixes from a base CIDR.
Example fix
# before (HCL)
output "ip" {
value = cidrhost(var.base_cidr, 5)
}
# var.base_cidr = "10.0.0.0" (no mask) -> invalid CIDR expression
# after
output "ip" {
value = cidrhost("10.0.0.0/16", 5)
}
# or guard:
output "ip" {
value = var.base_cidr != "" ? cidrhost(var.base_cidr, 5) : null
} Defensive patterns
Strategy: validation
Validate before calling
# (HCL) guard before calling cidrhost
output "ip" {
value = var.cidr != "" && can(regex("/.+", var.cidr)) ? cidrhost(var.cidr, 5) : null
} Type guard
// (Go) true if the string is parseable as CIDR
func isValidCIDR(s string) bool {
_, _, err := net.ParseCIDR(s)
return err == nil
} Try / catch
# (HCL) use try to fall back gracefully value = try(cidrhost(var.cidr, 5), null)
Prevention
- Always include the /mask in cidrhost prefixes.
- Guard empty/null computed prefixes with a conditional.
- Derive prefixes from a validated base CIDR via cidrsubnet.
- Use can()/try() to degrade gracefully on bad input.
When it happens
Trigger: Calling cidrhost(prefix, hostnum) where prefix is not valid CIDR: missing /mask (e.g. "10.0.0.0"), host bits set in what should be a network (some parsers reject), invalid octets, or a non-IP string. The function then returns cty.UnknownVal(String) plus this error.
Common situations: Forgetting the /mask in cidrhost("10.0.0.0", 5), passing a variable that is null/empty at evaluate time, a computed CIDR that resolves to a bare IP, IPv4/IPv6 formatting mistakes, or copy-paste of a gateway IP instead of a network prefix.
Related errors
- IPv6 addresses cannot have a netmask: %s
- lookup() takes two or three arguments, got %d
- lookup failed to find key %s
- empty state name
- Attempted to initialize pluggable state with an empty string
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/b6e2f769cf8d6e89.
Report an issue: GitHub.