docker/cli · error
unrecognized service mode
Error message
unrecognized service mode
What it means
In `progress.initializeUpdater()` (progress.go:234-253), the function inspects the service's `Spec.Mode` field to select the appropriate progress updater (replicated, global, replicated-job, or global-job). If none of the four mode sub-structs (`Replicated`, `Global`, `ReplicatedJob`, `GlobalJob`) is non-nil, the function falls through to line 253 and returns this error. Under normal operation, a Docker Swarm service always has exactly one mode set. This error indicates a corrupt or unexpected service spec — possibly from a newer engine API with an unrecognized mode, or data corruption.
Solutions
- Verify the service mode using `docker service inspect --format '{{.Spec.Mode}}' <service>` — if the mode is empty or unrecognized, the service spec is corrupt
- Upgrade the Docker CLI to match or exceed the Docker Engine version
- Recreate the service with a known mode (`--mode replicated`, `global`, `replicated-job`, or `global-job`)
Example fix
# diagnose the service mode
docker service inspect --format '{{json .Spec.Mode}}' myservice
# if mode is empty/corrupt, recreate the service
docker service rm myservice
docker service create --name myservice --mode replicated --replicas 3 --image nginx Defensive patterns
Strategy: try-catch
Validate before calling
// Before calling ServiceProgress, verify the service mode is recognized
func isRecognizedMode(mode swarm.ServiceMode) bool {
return mode.Replicated != nil || mode.Global != nil ||
mode.ReplicatedJob != nil || mode.GlobalJob != nil
}
// Usage:
// res, _ := apiClient.ServiceInspect(ctx, svcID, opts)
// if !isRecognizedMode(res.Service.Spec.Mode) {
// return errors.New("service has no recognized mode")
// } Type guard
// Type guard for swarm.ServiceMode
defunc hasKnownServiceMode(m swarm.ServiceMode) bool {
return m.Replicated != nil || m.Global != nil ||
m.ReplicatedJob != nil || m.GlobalJob != nil
} Try / catch
// Wrap ServiceProgress in error handling
err := progress.ServiceProgress(ctx, apiClient, svcID, progressWriter)
if err != nil && strings.Contains(err.Error(), "unrecognized service mode") {
// Service spec is corrupt or CLI version is too old for this mode
log.Printf("service %s has an unrecognized mode; inspect manually: %v", svcID, err)
// Fall back to non-blocking monitoring
return nil
} Prevention
- Ensure the Docker CLI version matches or exceeds the Docker Engine version
- Validate the service mode before calling ServiceProgress
- Recreate corrupt services with a known, standard mode
When it happens
Trigger: Calling `ServiceProgress()` on a service whose `Spec.Mode` has all four sub-structs nil. This is an internal invariant violation — it should not happen with services created by the standard Docker API. Could theoretically occur if the swarm store is corrupted, or if a future API version introduces a new mode that this CLI version does not recognize.
Common situations: Version skew: an older CLI connected to a newer Docker Engine that supports a service mode the CLI does not know about. Or a manually constructed/corrupted swarm service object passed to the progress API.
Related errors
- no replica count
- placement preference must be of the format
- replicas can only be used with replicated or replicated-job…
- replicas-max-per-node can only be used with replicated or…
- max-concurrent can only be used with replicated-job mode
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/5627b3e3c2d76792.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/service/progress/progress.go:253
if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil {
return &replicatedProgressUpdater{
progressOut: progressOut,
}, nil
}
if service.Spec.Mode.Global != nil {
return &globalProgressUpdater{
progressOut: progressOut,
}, nil
}
if service.Spec.Mode.ReplicatedJob != nil {
return newReplicatedJobProgressUpdater(service, progressOut), nil
}
if service.Spec.Mode.GlobalJob != nil {
return &globalJobProgressUpdater{
progressOut: progressOut,
}, nil
}
return nil, errors.New("unrecognized service mode")
}
func writeOverallProgress(progressOut progress.Output, numerator, denominator int, rollback bool) {
if rollback {
progressOut.WriteProgress(progress.Progress{
ID: "overall progress",
Action: fmt.Sprintf("rolling back update: %d out of %d tasks", numerator, denominator),
})
return
}
progressOut.WriteProgress(progress.Progress{
ID: "overall progress",
Action: fmt.Sprintf("%d out of %d tasks", numerator, denominator),
})
}
func truncError(errMsg string) string {
// Remove newlines from the error, which corrupt the output.View on GitHub (pinned to 4f84911bfe)