docker/cli · error
missing mandatory field
Error message
missing mandatory field '%s'
What it means
Thrown by PortOpt.Set (port.go:101) when the long-syntax --publish value has no `target` field, leaving TargetPort at its zero value (0). The target/container port is mandatory in long syntax; published, protocol, and mode are optional with defaults.
Solutions
- Always include target in long syntax: `--publish published=8080,target=80`.
- target is the in-container port the service listens on; it cannot be defaulted.
- Use short syntax `--publish 8080:80` if you prefer the compact form (both ports mandatory there too).
- Pre-check that the parsed fields contain a 'target' key.
Example fix
// before --publish published=8080,mode=ingress // after --publish published=8080,target=80,mode=ingress
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the long-syntax --publish value contains a target field.
hasTarget := false
for _, f := range strings.Split(pubVal, ",") {
if k, _, _ := strings.Cut(strings.ToLower(strings.TrimSpace(f)), "="); k == "target" {
hasTarget = true
}
}
if !hasTarget { return errors.New("target port is required") } Prevention
- Always include target=N in long syntax.
- Remember target is the in-container port and is mandatory.
- Use short syntax a:b as an alternative (both ports required).
- Pre-scan parsed fields for the 'target' key.
When it happens
Trigger: Passing `--publish published=8080,protocol=tcp` with no `target=`, or any long-syntax string that omits target. After the field loop, pConfig.TargetPort == 0, so line 101 fires.
Common situations: Assuming the container port is inferred from the published port, forgetting the target field, or copy-paste that drops it.
Related errors
- invalid field
- invalid protocol value
- invalid publish mode value
- invalid target port ( ): value must be an integer
- invalid published port
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/1d51844427403302.
Report an issue: GitHub.
Appendix: source
Thrown at opts/swarmopts/port.go:101
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})
if err != nil {
return err
}
for _, portBindings := range portBindingMap {
for _, portBinding := range portBindings {
if portBinding.HostIP != "" {
return errors.New("hostip is not supported")
}
}
}View on GitHub (pinned to 4f84911bfe)