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

  1. Use a single integer or a clean `low-high` range for the host port: `--publish 8080:80` or `--publish 8080-8082:80`.
  2. Put the protocol after a '/', not in the host slot: `--publish 8080:80/udp`.
  3. Remove letters/extra separators from the host port.
  4. 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

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


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)