docker/cli · error

invalid publish mode value

Error message

invalid publish mode value (%s): must be either '%s' or '%s'

What it means

Thrown by PortOpt.Set (port.go:71) when the `mode` field is neither 'ingress' nor 'host'. Swarm service port publish modes are limited to these two values; the switch over swarm.PortConfigPublishMode(val) matches only PortConfigPublishModeIngress and PortConfigPublishModeHost, so any other string hits the default case.

Solutions

  1. Use mode=ingress (default, routing mesh) or mode=host (bypass mesh, host-native).
  2. Double-check spelling: 'ingress' not 'ingres', 'host' not 'hosts'.
  3. If unsure, omit the mode field to get the default (ingress).
  4. Remember: these are publish modes, not network drivers.

Example fix

// before
--publish target=80,mode=bridge
// after
--publish target=80,mode=ingress   (or mode=host to bypass the routing mesh)
Defensive patterns

Strategy: validation

Validate before calling

// Restrict publish mode to ingress/host.
var okMode = map[string]bool{"ingress": true, "host": true}
if !okMode[strings.ToLower(modeVal)] {
    return fmt.Errorf("mode %q must be ingress or host", modeVal)
}

Prevention

When it happens

Trigger: Passing `--publish target=80,mode=bridge`, `mode=mesh`, `mode=global`, or a typo like `mode=ingres`. swarm.PortConfigPublishMode(val) yields a value not equal to either constant, firing line 71.

Common situations: Confusing swarm publish modes with Docker network drivers (bridge/host as a driver), typos, or assuming 'global' (a service mode) is a publish mode.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/cad287813df756b0. Report an issue: GitHub.

Appendix: source

Thrown at opts/swarmopts/port.go:71

			// 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)
				}

				pConfig.TargetPort = uint32(tPort)
			case portOptPublishedPort:
				pPort, err := strconv.ParseUint(val, 10, 16)
				if err != nil {
					var numErr *strconv.NumError
					if errors.As(err, &numErr) {
						err = numErr.Err

View on GitHub (pinned to 4f84911bfe)