kubernetes/kops · error

label %q already set to %q while it should be %q

Error message

label %q already set to %q while it should be %q

What it means

addLabels enforces the addon's declared selector labels: before copying addon.Selector onto each object, it rejects objects where the label key already exists with a different value, since kops cannot reconcile contradictory ownership/selector labels. This prevents silently relabeling objects that intentionally carry different values.

Source

Thrown at pkg/model/components/addonmanifests/remap.go:136

	for _, object := range objects {
		meta := &metav1.ObjectMeta{}
		err := object.Reparse(meta, "metadata")
		if err != nil {
			return fmt.Errorf("Failed to annotate %T", object)
		}

		if meta.Labels == nil {
			meta.Labels = make(map[string]string)
		}

		meta.Labels["app.kubernetes.io/managed-by"] = "kops"
		meta.Labels[KopsAddonLabelKey] = *addon.Name

		// ensure selector is set where applicable
		for key, val := range addon.Selector {
			existingVal, ok := meta.Labels[key]
			if ok && existingVal != val {
				return fmt.Errorf("label %q already set to %q while it should be %q", key, meta.Labels[key], val)
			}

			meta.Labels[key] = val
		}
		if hasPodSpecTemplate(object) {
			addPodSpecLabels(object)
		}
		object.Set(meta, "metadata")
	}
	return nil
}

func addPodSpecLabels(object *kubemanifest.Object) error {
	podMeta := &metav1.ObjectMeta{}

	if err := object.Reparse(podMeta, "spec", "template", "metadata"); err != nil {
		return fmt.Errorf("failed to parse spec.template.spec from Deployment: %v", err)
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Change the object's existing label value to match the addon selector, or remove it so the selector value is applied
  2. Update the AddonSpec selector to the value already present in the manifest if the existing value is intentional
  3. Check for copy-pasted labels from another addon and reassign a unique key
  4. Restore the stock manifest and re-apply your customization via supported overrides

Example fix

# before
metadata:
  labels:
    k8s-app: my-dns
# after (match addon.Selector)
metadata:
  labels:
    k8s-app: kube-dns
Defensive patterns

Strategy: validation

Validate before calling

// Detect selector conflicts before remapping:
for key, want := range addon.Selector {
    for _, obj := range objects {
        meta := &metav1.ObjectMeta{}
        if err := obj.Reparse(meta, "metadata"); err != nil { continue }
        if have, ok := meta.Labels[key]; ok && have != want {
            return fmt.Errorf("conflict: %s has %s=%s, selector wants %s", obj.Kind(), key, have, want)
        }
    }
}

Try / catch

if err := addLabels(addon, objects); err != nil {
    var conflict *LabelConflictError
    if errors.As(err, &conflict) { /* adjust selector or labels */ }
    return fmt.Errorf("failed to annotate %q: %w", name, err)
}

Prevention

When it happens

Trigger: RemapAddonManifest on an addon whose AddonSpec.Selector declares key K=V, while an object in the manifest already has label K set to a value != V.

Common situations: Customized manifests where a user changed a selector label (e.g. k8s-app: kube-dns changed to k8s-app: my-dns); addon spec updated upstream to select on a new label that collides with an existing one; copy-pasted labels across addons.

Related errors


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