docker/cli · error

`-- ` flag requires the `--rotate` flag to update the CA

Error message

`--%s` flag requires the `--rotate` flag to update the CA

What it means

Emitted by 'docker swarm ca' when a CA-modifying flag (--ca-cert, --ca-key, --cert-expiry, --external-ca) is supplied without --rotate. The command treats these flags as side effects of a rotation; without --rotate it only displays the current trust root.

Solutions

  1. Add --rotate: 'docker swarm ca --rotate --ca-cert ./new.pem'.
  2. If you only meant to view the CA, drop the offending CA-modifying flags entirely.
  3. Verify the exact flag name with 'docker swarm ca --help'.

Example fix

# before
docker swarm ca --ca-cert ./new.pem

# after
docker swarm ca --rotate --ca-cert ./new.pem
Defensive patterns

Strategy: validation

Validate before calling

// Validate CA flag set before invoking
needsRotate := anyChanged(flags, flagCACert, flagCAKey, flagCertExpiry, flagExternalCA)
if needsRotate && !flags.Changed(flagRotate) {
    return errors.New("--rotate is required when changing CA cert/key/expiry/external-ca")
}

Type guard

func requiresRotate(flags *pflag.FlagSet) bool {
	for _, f := range []string{flagCACert, flagCAKey, flagCertExpiry, flagExternalCA} {
		if flags.Changed(f) {
			return true
		}
	}
	return false
}

Prevention

When it happens

Trigger: Invoking 'docker swarm ca --ca-cert ./new.pem' (or --ca-key / --cert-expiry / --external-ca) with no --rotate flag. The loop at ca.go:67-70 detects any of those flags as Changed and returns this error.

Common situations: Operator forgets that updating the CA is destructive and must be explicitly requested; scripting that reuses an init-style flag set for ca; typo'd --rotate (e.g. --rotat).

Related errors


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

Appendix: source

Thrown at cli/command/swarm/ca.go:69

	flags.Var(&opts.rootCAKey, flagCAKey, "Path to the PEM-formatted root CA key to use for the new cluster")

	flags.BoolVarP(&opts.detach, "detach", "d", false, "Exit immediately instead of waiting for the root rotation to converge")
	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress progress output")
	return cmd
}

func runCA(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, opts caOptions) error {
	apiClient := dockerCLI.Client()

	res, err := apiClient.SwarmInspect(ctx, client.SwarmInspectOptions{})
	if err != nil {
		return err
	}

	if !opts.rotate {
		for _, f := range []string{flagCACert, flagCAKey, flagCertExpiry, flagExternalCA} {
			if flags.Changed(f) {
				return fmt.Errorf("`--%s` flag requires the `--rotate` flag to update the CA", f)
			}
		}
		return displayTrustRoot(dockerCLI.Out(), res)
	}

	if flags.Changed(flagExternalCA) && len(opts.externalCA.Value()) > 0 && !flags.Changed(flagCACert) {
		return fmt.Errorf(
			"rotating to an external CA requires the `--%s` flag to specify the external CA's cert - "+
				"to add an external CA with the current root CA certificate, use the `update` command instead", flagCACert)
	}

	if flags.Changed(flagCACert) && len(opts.externalCA.Value()) == 0 && !flags.Changed(flagCAKey) {
		return fmt.Errorf("the --%s flag requires that a --%s flag and/or --%s flag be provided as well",
			flagCACert, flagCAKey, flagExternalCA)
	}

	updateSwarmSpec(&res.Swarm.Spec, flags, opts)
	if _, err := apiClient.SwarmUpdate(ctx, client.SwarmUpdateOptions{

View on GitHub (pinned to 4f84911bfe)