docker/cli · error
invalid hostport binding
Error message
invalid hostport binding (%s) for port (%d)
What it means
Thrown by ConvertPortToPortConfig (port.go:172) when, in short syntax, the host-port portion of a binding cannot be parsed as a valid port or port range by network.ParsePortRange. Only fired when HostPort is non-empty (empty is allowed at line 171). The host port string must be a single integer or an a-b range.
Solutions
- Use a single integer or a clean `low-high` range for the host port: `--publish 8080:80` or `--publish 8080-8082:80`.
- Put the protocol after a '/', not in the host slot: `--publish 8080:80/udp`.
- Remove letters/extra separators from the host port.
- Pre-validate ranges with network.ParsePortRange before passing.
Example fix
// before --publish 8080-9090-100:80 // after --publish 8080-9090:80
Defensive patterns
Strategy: validation
Validate before calling
// Validate the short-syntax host port / range before submission.
if binding.HostPort != "" {
if _, err := network.ParsePortRange(binding.HostPort); err != nil {
return fmt.Errorf("host port %q is not a valid port or range", binding.HostPort)
}
} Prevention
- Use a single integer or a clean low-high range for the host port.
- Put protocol after '/', not in the host slot.
- Avoid multiple dashes (low-high only, one separator).
- Pre-validate with network.ParsePortRange.
When it happens
Trigger: Passing `--publish abc:80`, `8080-9090-100:80`, `80http:80`, or any short-syntax value whose left-of-colon host part is non-empty and malformed. ParsePortRange returns an error, line 172 wraps it.
Common situations: Typos in the published port, accidental inclusion of protocol/units in the host slot, malformed ranges (two dashes), or stray characters from shell expansion.
Related errors
- invalid field
- invalid protocol value
- invalid publish mode value
- invalid target port ( ): value must be an integer
- invalid published port
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/c587496137e2c9cc.
Report an issue: GitHub.
Appendix: source
Thrown at opts/swarmopts/port.go:172
func (p *PortOpt) Value() []swarm.PortConfig {
return p.ports
}
// ConvertPortToPortConfig converts ports to the swarm type
func ConvertPortToPortConfig(
portProto network.Port,
portBindings map[nat.Port][]nat.PortBinding,
) ([]swarm.PortConfig, error) {
ports := make([]swarm.PortConfig, 0, len(portBindings))
for _, binding := range portBindings[nat.Port(portProto.String())] {
if p := net.ParseIP(binding.HostIP); p != nil && !p.IsUnspecified() {
// TODO(thaJeztah): use context-logger, so that this output can be suppressed (in tests).
logrus.Warnf("ignoring IP-address (%s:%s) service will listen on '0.0.0.0'", net.JoinHostPort(binding.HostIP, binding.HostPort), portProto.String())
}
pr, err := network.ParsePortRange(binding.HostPort)
if err != nil && binding.HostPort != "" {
return nil, fmt.Errorf("invalid hostport binding (%s) for port (%d)", binding.HostPort, portProto.Num())
}
for p := range pr.All() {
ports = append(ports, swarm.PortConfig{
// TODO Name: ?
Protocol: portProto.Proto(),
TargetPort: uint32(portProto.Num()),
PublishedPort: uint32(p.Num()),
PublishMode: swarm.PortConfigPublishModeIngress,
})
}
}
return ports, nil
}
View on GitHub (pinned to 4f84911bfe)