kubernetes/kops · error
error patching status: %w
Error message
error patching status: %w
What it means
In the KopsConfig bootstrap controller's Reconcile, after storing the bootstrap-data secret, the controller updates the KopsConfig object's status (DataSecretName, Ready) with client.Status().Update. This error wraps any failure of that status update — most commonly an optimistic-concurrency conflict because the object changed since it was fetched.
Source
Thrown at pkg/controllers/clusterapi/kopsconfig_controller.go:107
return ctrl.Result{}, err
}
kopsControlPlane, err := getKopsControlPlaneFromCAPICluster(ctx, r.client, capiCluster)
if err != nil {
return ctrl.Result{}, err
}
data, err := r.buildBootstrapData(ctx, cluster, kopsControlPlane)
if err != nil {
return ctrl.Result{}, err
}
if err := r.storeBootstrapData(ctx, obj, data); err != nil {
return ctrl.Result{}, err
}
if err := r.client.Status().Update(ctx, obj); err != nil {
return ctrl.Result{}, fmt.Errorf("error patching status: %w", err)
}
return ctrl.Result{}, nil
}
// storeBootstrapData creates a new secret with the data passed in as input,
// sets the reference in the configuration status and ready to true.
func (r *KopsConfigReconciler) storeBootstrapData(ctx context.Context, parent *api.KopsConfig, data []byte) error {
// log := ctrl.LoggerFrom(ctx)
clusterName := parent.Labels[clusterv1.ClusterNameLabel]
if clusterName == "" {
return fmt.Errorf("cluster name label %q not yet set", clusterv1.ClusterNameLabel)
}
secretName := types.NamespacedName{
Namespace: parent.GetNamespace(),
Name: parent.GetName(),View on GitHub (pinned to 4c8573c808)
Solutions
- Simply requeue — controller-runtime retries and the conflict resolves on the next reconcile with fresh resourceVersion
- Use a merge patch (client.Status().Patch with client.MergeFrom) to reduce conflict likelihood
- Grant update/patch on kopsconfigs/status to the controller ServiceAccount
- Check API-server health/etcd latency if conflicts persist at scale
Example fix
// before
if err := r.client.Status().Update(ctx, obj); err != nil {
return ctrl.Result{}, fmt.Errorf("error patching status: %w", err)
}
// after: use patch to reduce optimistic-concurrency conflicts
patch := client.MergeFrom(obj.DeepCopy())
obj.Status.DataSecretName = pointer.String(secret.Name)
obj.Status.Ready = true
if err := r.client.Status().Patch(ctx, obj, patch); err != nil {
if apierrors.IsConflict(err) {
return ctrl.Result{RequeueAfter: time.Second}, nil
}
return ctrl.Result{}, fmt.Errorf("error patching status: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
kubectl auth can-i patch kopsconfigs.status -n <ns> --as=system:serviceaccount:<ns>:<sa> # or: kubectl auth can-i update kopsconfigs/status ...
Try / catch
if err := r.client.Status().Update(ctx, obj); err != nil {
if apierrors.IsConflict(err) {
return ctrl.Result{Requeue: true}, nil // stale resourceVersion, retry with fresh copy
}
return ctrl.Result{}, fmt.Errorf("error patching status: %w", err)
} Prevention
- Prefer Status().Patch with MergeFrom over Update to reduce conflicts
- Avoid external writers touching KopsConfig status
- Requeue on conflict instead of surfacing an error
- Check etcd/API-server latency if conflicts are persistent
When it happens
Trigger: The KopsConfig object was modified (resourceVersion bumped) between the initial Get and the Status().Update, producing a Conflict; the ServiceAccount lacks update permission on kopsconfigs/status; the API server rejects or times out the request.
Common situations: Frequent reconcile storms where the object is edited concurrently by another controller or user; controller RBAC missing status-update verbs; API server slowness/etcd timeouts.
Related errors
- error updating object: %w
- converting cluster object: %w
- building cloud: %w
- error updating SSHCredential: %v
- error adding needs-update label: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/13cd2d9595ec018d.
Report an issue: GitHub.