docker/cli ยท error
this node is not a swarm manager. Use "docker swarm init" or
Error message
this node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again
What it means
Emitted by `docker stack deploy` before any resources are created. checkDaemonIsSwarmManager (deploy.go:101-110) calls the Info API and requires Swarm.ControlAvailable; the pre-check exists because network creation in the global scope does not return a proper status code when the daemon isn't a manager, so the CLI verifies manager status up front.
Source
Thrown at cli/command/stack/deploy.go:107
if opts.detach && !flags.Changed("detach") {
_, _ = fmt.Fprintln(dockerCLI.Err(), "Since --detach=false was not specified, tasks will be created in the background.\n"+
"In a future release, --detach=false will become the default.")
}
return deployCompose(ctx, dockerCLI, opts, cfg)
}
// checkDaemonIsSwarmManager does an Info API call to verify that the daemon is
// a swarm manager. This is necessary because we must create networks before we
// create services, but the API call for creating a network does not return a
// proper status code when it can't create a network in the "global" scope.
func checkDaemonIsSwarmManager(ctx context.Context, dockerCli command.Cli) error {
res, err := dockerCli.Client().Info(ctx, client.InfoOptions{})
if err != nil {
return err
}
if !res.Info.Swarm.ControlAvailable {
return errors.New(`this node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again`)
}
return nil
}
// pruneServices removes services that are no longer referenced in the source
func pruneServices(ctx context.Context, dockerCLI command.Cli, namespace convert.Namespace, services map[string]struct{}) {
apiClient := dockerCLI.Client()
oldServices, err := getStackServices(ctx, apiClient, namespace.Name())
if err != nil {
_, _ = fmt.Fprintln(dockerCLI.Err(), "Failed to list services:", err)
}
toRemove := make([]swarm.Service, 0, len(oldServices.Items))
for _, service := range oldServices.Items {
if _, exists := services[namespace.Descope(service.Spec.Name)]; !exists {
toRemove = append(toRemove, service)
}View on GitHub (pinned to e9452d6e78)
Solutions
- On a single-node setup, run `docker swarm init` (add --advertise-addr <ip> if multiple interfaces) and retry the deploy
- If this host should join an existing swarm, run the `docker swarm join --token ...` command from `docker swarm join-token manager|worker` on a manager
- If it is a worker, run the deploy on a manager instead, or promote it with `docker node promote <node>` from a manager
- Check `docker info --format '{{.Swarm.LocalNodeState}} {{.Swarm.ControlAvailable}}'` and verify DOCKER_HOST/context targets the intended node
Example fix
# before docker stack deploy -c compose.yml mystack # this node is not a swarm manager... # after docker swarm init docker stack deploy -c compose.yml mystack
When it happens
Trigger: Running `docker stack deploy` against a daemon where Info reports Swarm.ControlAvailable == false: swarm mode never initialized, the node is a worker, or the node left the swarm.
Common situations: Fresh Docker install where `docker swarm init` was never run; running stack deploy on a worker node or via a context/DOCKER_HOST pointing at a worker; CI runners with ephemeral daemons that lose swarm state; a manager that was demoted or lost quorum.
Related errors
- cannot get label %s for service %s
- specify a Compose file (with --compose-file)
- failed to remove some resources from stack: %s
- unsupported type
- node ID not found in /info
AI-assisted analysis of docker/cli@e9452d6e78 (2026-08-01).
Data as JSON: /data/errors/8d725274c1d09dbb.json.
Report an issue: GitHub.