docker/cli · error
invalid subnet
Error message
invalid subnet: %w
What it means
Returned by subnetMatches (create.go:259) when net.ParseCIDR fails on a subnet string. It wraps the underlying parse error with %w so callers see both the reason and the failing value context. This function is invoked for every subnet/range/gateway/aux-address comparison, so any malformed CIDR anywhere in the IPAM flags surfaces here.
Solutions
- Provide the subnet in full CIDR form, e.g. 172.20.0.0/16.
- Strip whitespace/newlines from dynamically supplied subnet values.
- Validate the string with netip.ParsePrefix before passing it to the command.
Example fix
// before docker network create --subnet 172.20.0.0 net // after docker network create --subnet 172.20.0.0/16 net
Defensive patterns
Strategy: validation
Validate before calling
// Reject malformed CIDRs before they reach subnetMatches.
func validateCIDRs(subnets []string) error {
for _, s := range subnets {
if _, _, err := net.ParseCIDR(s); err != nil {
return fmt.Errorf("invalid subnet %q: %w", s, err)
}
}
return nil
} Type guard
// isCIDR narrows a string to a valid CIDR form.
func isCIDR(s string) bool {
_, _, err := net.ParseCIDR(s)
return err == nil
} Prevention
- Always include the /prefix in subnet strings.
- Trim whitespace from templated/env-derived subnet values.
- Parse with netip.ParsePrefix early in config loaders.
When it happens
Trigger: Passing a --subnet that is not valid CIDR notation: missing prefix length (`172.20.0.0`), bad octets (`172.300.0.0/16`), or non-IP text (`foo`). Also triggered by a --ip-range or --gateway string that subnetMatches is asked to interpret as a CIDR.
Common situations: Omitting the `/prefix`, typos in IP octets, trailing whitespace from a shell variable, or templating a subnet from a config that left it blank.
Related errors
- cannot configure multiple ranges
- no matching subnet for range
- cannot configure multiple gateways
- no matching subnet for gateway
- no matching subnet for aux-address
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/3ce5bee9fc4b810e.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/network/create.go:259
idl := make([]network.IPAMConfig, 0, len(iData))
for _, v := range iData {
idl = append(idl, *v)
}
return &network.IPAM{
Driver: options.driver,
Config: idl,
Options: options.driverOpts.GetAll(),
}, nil
}
func subnetMatches(subnet, data string) (bool, error) {
var ip net.IP
_, s, err := net.ParseCIDR(subnet)
if err != nil {
return false, fmt.Errorf("invalid subnet: %w", err)
}
if strings.Contains(data, "/") {
ip, _, err = net.ParseCIDR(data)
if err != nil {
return false, err
}
} else {
ip = net.ParseIP(data)
}
return s.Contains(ip), nil
}
View on GitHub (pinned to 4f84911bfe)