docker/cli · error

invalid published port

Error message

invalid published port (%s): value must be an integer: %w

What it means

Thrown by PortOpt.Set (port.go:91) when the `published` (host) port value cannot be parsed as an unsigned 16-bit integer. Same logic as the target-port check: strconv.ParseUint(val, 10, 16) on a non-numeric, out-of-range, or empty value, with the NumError unwrapped and wrapped into this message.

Solutions

  1. Provide an integer 0–65535 for published: `--publish published=8080`.
  2. Strip units/signs/whitespace from the value.
  3. Pre-validate with `strconv.ParseUint(val, 10, 16)`.
  4. If you don't need a fixed host port, omit published and let Swarm assign one.

Example fix

// before
--publish published=8080tcp,target=80
// after
--publish published=8080,target=80,protocol=tcp
Defensive patterns

Strategy: validation

Validate before calling

// Validate the published (host) port as a uint16 before Set.
if _, err := strconv.ParseUint(publishedVal, 10, 16); err != nil {
    return fmt.Errorf("published port %q must be an integer 0-65535", publishedVal)
}

Prevention

When it happens

Trigger: Passing `--publish published=abc`, `published=70000`, `published=-5`, or `published=` (empty). ParseUint fails, errors.As unwraps the cause, line 91 reports it.

Common situations: Typos, ports beyond 65535, negative values, empty env-var expansion, or accidentally putting the protocol in the published slot.

Related errors


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

Appendix: source

Thrown at opts/swarmopts/port.go:91

			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
					}
					return fmt.Errorf("invalid published port (%s): value must be an integer: %w", val, err)
				}

				pConfig.PublishedPort = uint32(pPort)
			default:
				return fmt.Errorf("invalid field key: %s", key)
			}
		}

		if pConfig.TargetPort == 0 {
			return fmt.Errorf("missing mandatory field '%s'", portOptTargetPort)
		}

		p.ports = append(p.ports, pConfig)
	} else {
		// short syntax ([ip:]public:private[/proto])
		//
		// TODO(thaJeztah): we need an equivalent that handles the "ip-address" part without depending on the nat package.
		ports, portBindingMap, err := nat.ParsePortSpecs([]string{value})

View on GitHub (pinned to 4f84911bfe)