docker/cli · error
invalid protocol value
Error message
invalid protocol value '%s'
What it means
Thrown by PortOpt.Set (port.go:64) when the `protocol` field value is not a recognized IP protocol. The switch over network.IPProtocol(val) only accepts tcp, udp, sctp (case-sensitive to whatever IPProtocol normalizes to); anything else falls to default and is rejected.
Solutions
- Use one of: tcp, udp, sctp for the protocol field.
- Check spelling and remove extra whitespace.
- If you don't need a non-standard protocol, omit the field (defaults to tcp).
- Verify network.IPProtocol accepts your value; it is strict.
Example fix
// before --publish published=8080,target=80,protocol=http // after --publish published=8080,target=80,protocol=tcp
Defensive patterns
Strategy: validation
Validate before calling
// Restrict protocol to the supported set.
var okProto = map[string]bool{"tcp": true, "udp": true, "sctp": true}
if !okProto[strings.ToLower(protocolVal)] {
return fmt.Errorf("protocol %q must be tcp, udp, or sctp", protocolVal)
} Prevention
- Use tcp, udp, or sctp only.
- Omit protocol to default to tcp.
- Don't confuse application protocols (http) with transport protocols.
- Validate against network.IPProtocol in wrappers.
When it happens
Trigger: Passing `--publish target=80,protocol=http`, `protocol=icmp`, `protocol=TCP6`, or a typo like `protocol=tc`. network.IPProtocol returns a value outside {TCP,UDP,SCTP} so the default case at line 63 fires.
Common situations: Assuming arbitrary protocol names are supported, typos, or using uppercase variants the normalizer doesn't accept. Also from copy-paste of an IANA protocol name like 'https'.
Related errors
- invalid field
- invalid publish mode value
- invalid target port ( ): value must be an integer
- invalid published port
- invalid field key
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/84b7387a26919771.
Report an issue: GitHub.
Appendix: source
Thrown at opts/swarmopts/port.go:64
}
pConfig := swarm.PortConfig{
Protocol: network.TCP,
PublishMode: swarm.PortConfigPublishModeIngress,
}
for _, field := range fields {
// TODO(thaJeztah): these options should not be case-insensitive.
key, val, ok := strings.Cut(strings.ToLower(field), "=")
if !ok || key == "" {
return fmt.Errorf("invalid field: %s", field)
}
switch key {
case portOptProtocol:
switch proto := network.IPProtocol(val); proto {
case network.TCP, network.UDP, network.SCTP:
pConfig.Protocol = proto
default:
return fmt.Errorf("invalid protocol value '%s'", val)
}
case portOptMode:
switch swarm.PortConfigPublishMode(val) {
case swarm.PortConfigPublishModeIngress, swarm.PortConfigPublishModeHost:
pConfig.PublishMode = swarm.PortConfigPublishMode(val)
default:
return fmt.Errorf("invalid publish mode value (%s): must be either '%s' or '%s'", val, swarm.PortConfigPublishModeIngress, swarm.PortConfigPublishModeHost)
}
case portOptTargetPort:
tPort, err := strconv.ParseUint(val, 10, 16)
if err != nil {
var numErr *strconv.NumError
if errors.As(err, &numErr) {
err = numErr.Err
}
return fmt.Errorf("invalid target port (%s): value must be an integer: %w", val, err)
}
View on GitHub (pinned to 4f84911bfe)