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

  1. Use one of: tcp, udp, sctp for the protocol field.
  2. Check spelling and remove extra whitespace.
  3. If you don't need a non-standard protocol, omit the field (defaults to tcp).
  4. 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

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


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)