{"record":{"id":"b3e4dc02588526e5","repo":"cilium/cilium","slug":"refusing-to-overwrite-synced-secret-s-s-without","errorCode":null,"errorMessage":"refusing to overwrite synced Secret %s/%s without ownership labels","messagePattern":"refusing to overwrite synced Secret (.+?)/(.+?) without ownership labels","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"operator/pkg/secretsync/ownership.go","lineNumber":51,"sourceCode":"\t}\n\n\treturn types.NamespacedName{Namespace: namespace, Name: name}, true\n}\n\nfunc isOwnedBy(obj client.Object, owner types.NamespacedName, namespaceLabel, nameLabel string) bool {\n\texistingOwner, ok := ownerFromLabels(obj, namespaceLabel, nameLabel)\n\treturn ok && existingOwner == owner\n}\n\nfunc ensureOwnedBy(existing, desired client.Object, namespaceLabel, nameLabel string) error {\n\tdesiredOwner, ok := ownerFromLabels(desired, namespaceLabel, nameLabel)\n\tif !ok {\n\t\treturn fmt.Errorf(\"desired synced Secret %s/%s is missing ownership labels\", desired.GetNamespace(), desired.GetName())\n\t}\n\n\texistingOwner, ok := ownerFromLabels(existing, namespaceLabel, nameLabel)\n\tif !ok {\n\t\treturn fmt.Errorf(\"refusing to overwrite synced Secret %s/%s without ownership labels\", existing.GetNamespace(), existing.GetName())\n\t}\n\tif existingOwner != desiredOwner {\n\t\treturn fmt.Errorf(\"refusing to overwrite synced Secret %s/%s owned by %s/%s with data from %s/%s\", existing.GetNamespace(), existing.GetName(), existingOwner.Namespace, existingOwner.Name, desiredOwner.Namespace, desiredOwner.Name)\n\t}\n\n\treturn nil\n}\n\nfunc setSourceAnnotations(obj client.Object, kind string, source types.NamespacedName) {\n\tannotations := make(map[string]string, len(obj.GetAnnotations())+3)\n\tmaps.Copy(annotations, obj.GetAnnotations())\n\n\tannotations[SourceKindAnnotation] = kind\n\tannotations[SourceNamespaceAnnotation] = source.Namespace\n\tannotations[SourceNameAnnotation] = source.Name\n\n\tobj.SetAnnotations(annotations)\n}","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/cilium/cilium/blob/ac7b90affa4baf0642e6685319d56907b3a73a6d/operator/pkg/secretsync/ownership.go#L33-L69","documentation":"ensureOwnedBy also validates the existing (target) Secret: if it lacks ownership labels, the sync refuses to overwrite it, because overwriting an unlabeled secret could clobber a secret not managed by the sync (or one whose ownership history was lost). This is a safety guard against hijacking pre-existing secrets.","triggerScenarios":"ensureSyncedSecret finds an existing Secret in the cluster whose labels do not contain the ownership keys, and attempts to overwrite it with desired content.","commonSituations":"A same-named Secret pre-exists (created manually or by another controller) before cilium's sync runs; labels were stripped by another tool; or an upgrade changed the label keys so old secrets appear unlabeled.","solutions":["Delete the unlabeled conflicting Secret and let the sync recreate it with proper ownership labels","Re-add the correct Cilium ownership labels to the existing Secret","Rename your pre-existing Secret or the synced Secret to avoid the collision","Verify ownership label keys match the current Cilium version's expectations"],"exampleFix":"# before\nkubectl create secret generic my-secret ... # collides with synced name\n# after\nkubectl delete secret my-secret -n ns && kubectl annotate secret ... # or rename to my-secret-manual","handlingStrategy":"validation","validationCode":"existing := &corev1.Secret{}\nerr := cl.Get(ctx, key, existing)\nif err == nil && !isOwnershipLabeled(existing, namespaceLabel, nameLabel) {\n    return fmt.Errorf(\"conflict: secret %s exists without cilium ownership labels; rename or delete it first\", key)\n}","typeGuard":"func isOwnershipLabeled(o client.Object, nsLabel, nameLabel string) bool {\n    l := o.GetLabels()\n    _, ns := l[nsLabel]; _, n := l[nameLabel]\n    return ns && n\n}","tryCatchPattern":"if err := ensureSyncedSecret(ctx, cl, reg, key); err != nil {\n    if strings.Contains(err.Error(), \"without ownership labels\") {\n        // delete the unlabeled secret (after confirming it is not user-managed), then retry\n    }\n    return err\n}","preventionTips":["Avoid pre-creating Secrets with the names cilium will sync into","After upgrades that change label keys, re-run the sync registration to relabel existing secrets","Document that cilium-synced Secrets are managed objects and must not be hand-edited"],"tags":["cilium","kubernetes","secrets","operator","ownership-conflict"],"backgroundTag":"missing-ownership-labels","analyzedSha":"ac7b90affa4baf0642e6685319d56907b3a73a6d","analyzedAt":"2026-08-31T18:27:15.868Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}