docker/cli · error

could not fetch unlock key

Error message

could not fetch unlock key: %w

What it means

Emitted by 'docker swarm unlock-key' when the final SwarmGetUnlockKey RPC fails (after an optional rotation). The rotation/update path has its own earlier checks; this wraps the read call at unlock_key.go:73-75.

Solutions

  1. Ensure the active context targets a manager: 'docker node ls'.
  2. Retry once the manager is reachable ('docker info' shows swarm active).
  3. Run with --debug to inspect the wrapped underlying error.

Example fix

# before: unlock-key fetch against an unhealthy manager
docker swarm unlock-key

# after: target a healthy manager then retry
docker context use manager-prod
docker node ls
docker swarm unlock-key
Defensive patterns

Strategy: retry

Validate before calling

// Confirm manager before fetching key
if info, err := apiClient.Info(ctx); err != nil || !info.Swarm.ControlAvailable {
    return errors.New("unlock-key requires a healthy manager")
}

Type guard

func isUnlockKeyFetchErr(err error) bool {
	return err != nil && strings.Contains(err.Error(), "could not fetch unlock key:")
}

Try / catch

resp, err := apiClient.SwarmGetUnlockKey(ctx)
if err != nil {
    // backoff and retry once
    time.Sleep(retryBackoff)
    resp, err = apiClient.SwarmGetUnlockKey(ctx)
}
return resp, err

Prevention

When it happens

Trigger: Running 'docker swarm unlock-key' (or with --rotate) when the manager cannot return the key: connection error, manager down, API/version issue, or autolock disabled (though disabled yields a different 'no unlock key is set' message only after a successful fetch).

Common situations: Manager lost quorum; CLI context pointing at a worker not a manager; transient network blip; daemon restarting.

Related errors


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

Appendix: source

Thrown at cli/command/swarm/unlock_key.go:75

		_, err = apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{
			Version: res.Swarm.Version,
			Spec:    res.Swarm.Spec,

			RotateManagerUnlockKey: true,
		})
		if err != nil {
			return err
		}

		if !opts.quiet {
			_, _ = fmt.Fprintln(dockerCLI.Out(), "Successfully rotated manager unlock key.")
		}
	}

	resp, err := apiClient.SwarmGetUnlockKey(ctx)
	if err != nil {
		return fmt.Errorf("could not fetch unlock key: %w", err)
	}

	if resp.Key == "" {
		return errors.New("no unlock key is set")
	}

	if opts.quiet {
		_, _ = fmt.Fprintln(dockerCLI.Out(), resp.Key)
		return nil
	}

	printUnlockCommand(dockerCLI.Out(), resp.Key)
	return nil
}

func printUnlockCommand(out io.Writer, unlockKey string) {
	if len(unlockKey) > 0 {
		_, _ = fmt.Fprintf(out, "To unlock a swarm manager after it restarts, "+

View on GitHub (pinned to 4f84911bfe)