docker/cli · error

can only update cluster volumes

Error message

can only update cluster volumes

What it means

Returned by runUpdate (volume/update.go:54-56) when 'docker volume update' is run against a volume whose ClusterVolume field is nil, i.e. a normal local volume rather than a Swarm/cluster volume. The update API only mutates cluster-volume properties (currently Availability), so a non-cluster volume is rejected up front after the VolumeInspect call at line 49.

Solutions

  1. Use 'docker volume update' only on cluster volumes (created with cluster options / on a Swarm manager).
  2. For a local volume you want to remove, just run 'docker volume rm <name>' (no drain step needed).
  3. Verify the volume type with 'docker volume inspect <name>' and check for a non-null ClusterVolume section.

Example fix

# before (local volume)
docker volume update --availability drain mydata
docker volume rm mydata

# after (local volumes need no drain)
docker volume rm mydata
Defensive patterns

Strategy: validation

Validate before calling

// Before calling 'docker volume update --availability ...', confirm the volume is a cluster volume.
func isClusterVolume(apiClient client.APIClient, ctx context.Context, name string) (bool, error) {
    res, err := apiClient.VolumeInspect(ctx, name, client.VolumeInspectOptions{})
    if err != nil {
        return false, err
    }
    return res.Volume.ClusterVolume != nil, nil
}

Type guard

// canUpdateVolume reports whether the volume supports 'docker volume update'.
func canUpdateVolume(v *volume.Volume) bool {
    return v != nil && v.ClusterVolume != nil
}

Prevention

When it happens

Trigger: Running 'docker volume update --availability drain <local-volume-name>' where <local-volume-name> was created by 'docker volume create' (not a cluster volume). res.Volume.ClusterVolume is nil for local volumes, triggering the check at line 54.

Common situations: Confusing local volumes with Swarm cluster volumes (cluster volumes require Swarm and API 1.42+). Attempting to drain a local volume before deletion - a workflow only valid for cluster volumes (the comment at update.go:43-45 notes drain is needed before cluster-volume deletion).

Related errors


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

Appendix: source

Thrown at cli/command/volume/update.go:55

	_ = flags.SetAnnotation("availability", "swarm", []string{"manager"})

	return cmd
}

func runUpdate(ctx context.Context, dockerCli command.Cli, volumeID, availability string, flags *pflag.FlagSet) error {
	// TODO(dperny): For this earliest version, the only thing that can be
	// updated is Availability, which is necessary because to delete a cluster
	// volume, the availability must first be set to "drain"

	apiClient := dockerCli.Client()

	res, err := apiClient.VolumeInspect(ctx, volumeID, client.VolumeInspectOptions{})
	if err != nil {
		return err
	}

	if res.Volume.ClusterVolume == nil {
		return errors.New("can only update cluster volumes")
	}

	if flags.Changed("availability") {
		res.Volume.ClusterVolume.Spec.Availability = volume.Availability(availability)
	}
	_, err = apiClient.VolumeUpdate(ctx, res.Volume.ClusterVolume.ID, client.VolumeUpdateOptions{
		Version: res.Volume.ClusterVolume.Version,
		Spec:    &res.Volume.ClusterVolume.Spec,
	})
	return err
}

View on GitHub (pinned to 4f84911bfe)