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

  1. Provide the subnet in full CIDR form, e.g. 172.20.0.0/16.
  2. Strip whitespace/newlines from dynamically supplied subnet values.
  3. 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

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


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)