docker/cli · error
invalid range format for --expose
Error message
invalid range format for --expose: %w
What it means
Returned in opts.go:474 when network.ParsePortRange cannot parse a --expose token. --expose accepts either a single port[/proto] or a start-end[/proto] range; anything else fails.
Solutions
- Use the form PORT[/PROTO] or STARTPORT-ENDPORT[/PROTO].
- Ensure start <= end and ports are within 0-65535.
- Check for stray separators (.., --, etc.).
Example fix
# before docker run --expose 8080..9090 alpine # after docker run --expose 8080-9090 alpine
Defensive patterns
Strategy: validation
Validate before calling
import "github.com/docker/docker/api/types/network"
if _, err := network.ParsePortRange(expose); err != nil {
return fmt.Errorf("bad --expose %q: %w", expose, err)
} Type guard
func validPortRange(s string) bool {
_, err := network.ParsePortRange(s)
return err == nil
} Try / catch
// Deterministic: fix the token; do not retry.
if !validPortRange(tok) { /* drop or correct the token */ } Prevention
- Use PORT or START-END forms with optional /proto. Ensure start<=end and ports<=65535. Validate ranges in generated commands.
When it happens
Trigger: `docker run --expose <bad>`: non-numeric port, a range with the start greater than the end, a port above 65535, or malformed separators.
Common situations: Typo like --expose 8080..9090 (double dot), --expose 9000-8000 (reversed range), or --expose abc/tcp.
Related errors
- invalid publish opts format
- is not a valid mac address
- network is specified multiple times
- invalid pull option: ' ': must be one of , or
- copying config.json into container failed
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/1640a4542163d954.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/container/opts.go:474
}
// Add published ports as exposed ports.
exposedPorts := network.PortSet{}
for port := range ports {
p, err := network.ParsePort(string(port))
if err != nil {
return nil, err
}
exposedPorts[p] = struct{}{}
}
// Merge in exposed ports to the map of published ports
for _, e := range copts.expose.GetSlice() {
// support two formats for expose, original format <portnum>/[<proto>]
// or <startport-endport>/[<proto>]
pr, err := network.ParsePortRange(e)
if err != nil {
return nil, fmt.Errorf("invalid range format for --expose: %w", err)
}
// parse the start and end port and create a sequence of ports to expose
// if expose a port, the start and end port are the same
for p := range pr.All() {
exposedPorts[p] = struct{}{}
}
}
// validate and parse device mappings. Note we do late validation of the
// device path (as opposed to during flag parsing), as at the time we are
// parsing flags, we haven't yet sent a _ping to the daemon to determine
// what operating system it is.
devices := copts.devices.GetSlice()
deviceMappings := make([]container.DeviceMapping, 0, len(devices))
cdiDeviceNames := make([]string, 0, len(devices))
for _, device := range devices {
if cdi.IsQualifiedName(device) {
cdiDeviceNames = append(cdiDeviceNames, device)View on GitHub (pinned to 4f84911bfe)