kubernetes/kops · error

volume tag split failed, too few components for tag %q on vo

Error message

volume tag split failed, too few components for tag %q on volume %q

What it means

For each tagged etcd volume, findEtcdStatus looks for a tag containing TagKubernetesClusterIndex (the droplet index marker) and splits it on ':' expecting at least two parts ('<prefix>:<index>'). If the tag has no colon-separated index component, it aborts with this error because the droplet index cannot be extracted for getEtcdClusterSpec.

Source

Thrown at upup/pkg/fi/cloudup/do/cloud.go:349

		volumeID := volume.ID

		etcdClusterName := ""
		var etcdClusterSpec *etcd.EtcdClusterSpec

		for _, myTag := range volume.Tags {
			klog.V(8).Infof("findEtcdStatus status (from cloud): checking if volume with tag %q belongs to cluster", myTag)
			// check if volume belongs to this cluster.
			// tag will be in the format "KubernetesCluster:dev5-k8s-local" (where clusterName is dev5.k8s.local)
			clusterName := strings.ReplaceAll(cluster.Name, ".", "-")
			if strings.Contains(myTag, fmt.Sprintf("%s:%s", TagKubernetesClusterNamePrefix, clusterName)) {
				klog.V(10).Infof("findEtcdStatus cluster comparison matched for tag: %v", myTag)
				// this volume belongs to our cluster, add this to our etcdClusterSpec.
				// loop through the tags again and
				for _, volumeTag := range volume.Tags {
					if strings.Contains(volumeTag, TagKubernetesClusterIndex) {
						volumeTagParts := strings.Split(volumeTag, ":")
						if len(volumeTagParts) < 2 {
							return nil, fmt.Errorf("volume tag split failed, too few components for tag %q on volume %q", volumeTag, volume)
						}
						dropletIndex := volumeTagParts[1]
						etcdClusterSpec, err = c.getEtcdClusterSpec(volume.Name, dropletIndex)
						if err != nil {
							return nil, fmt.Errorf("error parsing etcd cluster tag %q on volume %q: %v", volumeTag, volumeID, err)
						}

						klog.V(10).Infof("findEtcdStatus etcdClusterSpec: %v", fi.DebugAsJsonString(etcdClusterSpec))
						etcdClusterName = etcdClusterSpec.ClusterKey
						status := statusMap[etcdClusterName]
						if status == nil {
							status = &kops.EtcdClusterStatus{
								Name: etcdClusterName,
							}
							statusMap[etcdClusterName] = status
						}

						memberName := etcdClusterSpec.NodeName

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Inspect the offending volume's tags (`doctl compute volume list`) and correct the index tag to '<prefix>:<index>' format.
  2. Exclude/fix volumes that belong to a different cluster but carry a partial tag set.
  3. Restore consistent tagging by letting kOps recreate the affected etcd volume (only if data loss is acceptable — etcd data is on it).
  4. Verify the kOps version writing tags matches the version reading them; avoid manual tag edits.

Example fix

// before
tags = ["kubernetes.io/cluster/mycluster"]
// after
tags = ["kubernetes.io/cluster/mycluster", "kubernetes.io/cluster/mycluster:1"]  // must include ":<dropletIndex>"
Defensive patterns

Strategy: validation

Validate before calling

for _, tag := range volume.Tags {
    if strings.Contains(tag, TagKubernetesClusterIndex) && len(strings.Split(tag, ":")) < 2 {
        return fmt.Errorf("malformed index tag %q on volume %s", tag, volume.ID)
    }
}

Try / catch

status, err := cloud.FindClusterStatus(cluster)
if err != nil && strings.Contains(err.Error(), "tag split failed") {
    return auditAndFixVolumeTags(cluster) // repair or ignore offending volume
}

Prevention

When it happens

Trigger: A volume in the cluster belongs to the cluster (cluster tag matched earlier) but carries a malformed index tag — e.g. tag is just the prefix with no ':N' suffix, tags were edited manually, or volumes were created by a different/kOps version writing a different tag format.

Common situations: Hand-edited DO volume tags; volumes reused/imported from another cluster or tooling; upgrading kOps across versions where tag naming changed; typos when seeding etcd volumes manually.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/aee658a6c778c3ce. Report an issue: GitHub.