docker/cli · error

%s: %w

Error message

%s: %w

What it means

Raised by waitOnServices (deploy path, --detach=false) when service.WaitOnService returns an error for a given serviceID. The %s is the service ID and %w wraps the underlying error (context cancellation, task failure reaching converge state, RPC error). Multiple per-service errors are joined with errors.Join.

Solutions

  1. Inspect the failing service's tasks: `docker service ps <serviceID>` and look at the error column.
  2. Resolve the underlying task failure (fix image, healthcheck, constraints, mounts).
  3. Redeploy; transient failures clear once the root cause is fixed.
  4. If you don't need to block on convergence, deploy with --detach and poll separately.

Example fix

// before: blocking deploy surfaces per-service converge failure
// after: diagnose the failing service's tasks
docker service ps --no-trunc <serviceID>
# read the ERROR column, fix root cause, then re-run:
docker stack deploy -c compose.yml mystack
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check likely convergence blockers: image pullability, healthcheck validity, constraints
for _, svc := range services {
    if svc.Healthcheck != nil && len(svc.Healthcheck.Test) == 0 {
        return fmt.Errorf("service %s healthcheck misconfigured", svc.Name)
    }
}

Try / catch

err := stackDeploy(ctx, cli, opts, cfg) // --detach=false
if err != nil {
    var joinErr interface{ Unwrap() []error }
    if errors.As(err, &joinErr) {
        for _, e := range joinErr.Unwrap() {
            // each is "<serviceID>: <cause>"; inspect tasks for that serviceID
        }
    }
}

Prevention

When it happens

Trigger: Running `docker stack deploy` without --detach (so waitOnServices runs at deploy_composefile.go:308), and one or more services fail to converge within the task wait, or the wait is interrupted. Each failing serviceID yields its own wrapped error.

Common situations: A service's tasks failing to start (bad image, crash loop, failed healthcheck); context deadline/cancellation (e.g. Ctrl-C during converge); manager communication error during the wait; tasks rejected by placement constraints.

Related errors


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

Appendix: source

Thrown at cli/command/stack/deploy_composefile.go:308

				EncodedRegistryAuth: encodedAuth,
				QueryRegistry:       queryRegistry,
			})
			if err != nil {
				return nil, fmt.Errorf("failed to create service %s: %w", name, err)
			}

			serviceIDs = append(serviceIDs, response.ID)
		}
	}

	return serviceIDs, nil
}

func waitOnServices(ctx context.Context, dockerCli command.Cli, serviceIDs []string, quiet bool) error {
	var errs []error
	for _, serviceID := range serviceIDs {
		if err := service.WaitOnService(ctx, dockerCli, serviceID, quiet); err != nil {
			errs = append(errs, fmt.Errorf("%s: %w", serviceID, err))
		}
	}
	return errors.Join(errs...)
}

View on GitHub (pinned to 4f84911bfe)