docker/cli · error
invalid field
Error message
invalid field: %s
What it means
Thrown by PortOpt.Set (port.go:56) when a field in the long-syntax --publish value lacks '=' or has an empty key. Long syntax looks like `published=8080,target=80,protocol=tcp,mode=ingress`; any field not matching key=value (or with an empty key after lowercasing) is rejected.
Solutions
- Use consistent long syntax: `--publish published=8080,target=80,protocol=tcp,mode=ingress`.
- Or use short syntax throughout: `--publish 8080:80`.
- Ensure every field has the form key=value with a non-empty key.
- Avoid stray commas that create empty fields.
Example fix
// before --publish published=8080,target // after --publish published=8080,target=80
Defensive patterns
Strategy: validation
Validate before calling
// Check each long-syntax --publish field is key=value with a non-empty key.
for _, f := range strings.Split(pubVal, ",") {
k, _, ok := strings.Cut(strings.ToLower(strings.TrimSpace(f)), "=")
if !ok || k == "" { return fmt.Errorf("publish field %q must be key=value", f) }
} Prevention
- Don't mix short (a:b) and long (k=v) syntax in one --publish.
- Always provide a value after '=' for each key.
- Watch for trailing commas creating empty fields.
- Prefer one syntax consistently per flag.
When it happens
Trigger: Passing `--publish published=8080,target` (no value for target), `--publish 8080:80,mode=ingress` (mixing short and long), or a field like `=tcp`. strings.Cut at line 54 yields ok=false or empty key.
Common situations: Mixing the short `IP:PUBLIC:PRIVATE/proto` form with key=value long form, truncating a field, copy-paste errors, or a missing '=' after a key.
Related errors
- invalid protocol value
- 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/87ef418f49b0de67.
Report an issue: GitHub.
Appendix: source
Thrown at opts/swarmopts/port.go:56
if err != nil {
return err
}
if longSyntax {
csvReader := csv.NewReader(strings.NewReader(value))
fields, err := csvReader.Read()
if err != nil {
return err
}
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)View on GitHub (pinned to 4f84911bfe)