{"record":{"id":"8ae9c47a31f3f03e","repo":"docker/cli","slug":"no-replica-count","errorCode":null,"errorMessage":"no replica count","messagePattern":"no replica count","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/command/service/progress/progress.go","lineNumber":296,"sourceCode":"\t\terrMsg = errMsg[:maxWidth-1] + \"…\"\n\t}\n\treturn errMsg\n}\n\ntype replicatedProgressUpdater struct {\n\tprogressOut progress.Output\n\n\t// used for mapping slots to a contiguous space\n\t// this also causes progress bars to appear in order\n\tslotMap map[int]int\n\n\tinitialized bool\n\tdone        bool\n}\n\nfunc (u *replicatedProgressUpdater) update(service swarm.Service, tasks []swarm.Task, activeNodes map[string]struct{}, rollback bool) (bool, error) {\n\tif service.Spec.Mode.Replicated == nil || service.Spec.Mode.Replicated.Replicas == nil {\n\t\treturn false, errors.New(\"no replica count\")\n\t}\n\treplicas := *service.Spec.Mode.Replicated.Replicas\n\n\tif !u.initialized {\n\t\tu.slotMap = make(map[int]int)\n\n\t\t// Draw progress bars in order\n\t\twriteOverallProgress(u.progressOut, 0, int(replicas), rollback)\n\n\t\tif replicas <= maxProgressBars {\n\t\t\tfor i := uint64(1); i <= replicas; i++ {\n\t\t\t\tprogress.Update(u.progressOut, fmt.Sprintf(\"%d/%d\", i, replicas), \" \")\n\t\t\t}\n\t\t}\n\t\tu.initialized = true\n\t}\n\n\ttasksBySlot := u.tasksBySlot(tasks, activeNodes)","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/command/service/progress/progress.go#L278-L314","documentation":"In `replicatedProgressUpdater.update()` (progress.go:294-296), the method re-checks that `service.Spec.Mode.Replicated` and `service.Spec.Mode.Replicated.Replicas` are non-nil. The updater was initialized in `initializeUpdater()` (line 235) only when both were non-nil, but `ServiceProgress` re-inspects the service on every loop iteration (line 93). If between iterations the service was updated to remove its replica count (e.g., mode changed to global), this re-check fails and returns the error. This is a race condition between progress monitoring and a concurrent service update.","triggerScenarios":"While `docker service create` (without `--detach`) is monitoring convergence progress, another process or user simultaneously updates the service to change its mode (e.g., `docker service update --mode global myservice`), causing the replicated mode or replica count to become nil on the next inspect.","commonSituations":"Concurrent service modifications during creation/convergence monitoring. Most likely in automation pipelines where one process creates the service and another immediately modifies it.","solutions":["Avoid modifying a service's mode while creation progress monitoring is running","Use `--detach` when creating the service if concurrent modifications are expected","Re-run `docker service ps <service>` to check status after the conflicting update completes"],"exampleFix":"# problematic: two concurrent operations\ndocker service create --name web --mode replicated --replicas 3 --image nginx &\n# simultaneously in another terminal:\ndocker service update --mode global web  # triggers the race\n\n# fix: use --detach to avoid blocking progress monitoring\ndocker service create --detach --name web --mode replicated --replicas 3 --image nginx","handlingStrategy":"try-catch","validationCode":"// Before calling ServiceProgress, ensure the service has a stable mode\nfunc hasStableReplicaCount(ctx context.Context, c client.APIClient, svcID string) bool {\n    res, err := c.ServiceInspect(ctx, svcID, client.ServiceInspectOptions{})\n    if err != nil {\n        return false\n    }\n    return res.Service.Spec.Mode.Replicated != nil &&\n        res.Service.Spec.Mode.Replicated.Replicas != nil\n}","typeGuard":null,"tryCatchPattern":"// Handle the race condition gracefully\nerr := progress.ServiceProgress(ctx, apiClient, svcID, progressWriter)\nif err != nil && strings.Contains(err.Error(), \"no replica count\") {\n    // Service mode likely changed concurrently; retry once or use --detach\n    log.Printf(\"service %s mode changed during progress monitoring\", svcID)\n}","preventionTips":["Avoid modifying a service's mode while progress monitoring is active","Use --detach for service creation if concurrent modifications are expected","Treat 'no replica count' as a transient race condition, not a permanent failure"],"tags":["docker","cli","service","swarm","progress","race-condition"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}