{"record":{"id":"2c21f820c04108bb","repo":"kubernetes/kops","slug":"error-updating-object-w","errorCode":null,"errorMessage":"error updating object: %w","messagePattern":"error updating object: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/applylib/applyset/unstructuredclient.go","lineNumber":104,"sourceCode":"\tname := nn.Name\n\tpatched, err := dynamicResource.Patch(ctx, name, patchType, data, opt)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error patching object: %w\", err)\n\t}\n\treturn patched, nil\n}\n\n// Update performs an Update operation on the object.  Generally we should prefer server-side-apply.\nfunc (c *UnstructuredClient) Update(ctx context.Context, obj *unstructured.Unstructured, opt metav1.UpdateOptions) (*unstructured.Unstructured, error) {\n\tgvk := obj.GroupVersionKind()\n\tdynamicResource, err := c.dynamicResource(ctx, gvk, obj.GetNamespace())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tupdated, err := dynamicResource.Update(ctx, obj, opt)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error updating object: %w\", err)\n\t}\n\treturn updated, nil\n}\n\n// Get reads the specified object.\nfunc (c *UnstructuredClient) Get(ctx context.Context, gvk schema.GroupVersionKind, nn types.NamespacedName) (*unstructured.Unstructured, error) {\n\tdynamicResource, err := c.dynamicResource(ctx, gvk, nn.Namespace)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tobj, err := dynamicResource.Get(ctx, nn.Name, metav1.GetOptions{})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not get existing object: %w\", err)\n\t}\n\n\treturn obj, nil\n}","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/applylib/applyset/unstructuredclient.go#L86-L122","documentation":"Update wraps errors from the dynamic resource client's Update call. Like the patch wrapper, it preserves the underlying API error; failures usually mean the object changed on the server (conflict), is invalid, or the request was rejected.","triggerScenarios":"Calling UnstructuredClient.Update on an unstructured object where the API server rejects the write: 409 Conflict on stale resourceVersion, 422 validation failure, 403 RBAC denial, or object not found.","commonSituations":"Optimistic-concurrency conflicts when another controller (or the same apply loop) modified the object; editing objects with defaulted/immutable fields; concurrent apply-set workers updating the same resource.","solutions":["Get a fresh copy of the object, re-apply your changes onto it, and retry Update (handles resourceVersion conflicts)","Inspect the wrapped error with apierrors.IsConflict/IsInvalid/IsForbidden to branch appropriately","For declarative workflows prefer server-side apply (Patch with ApplyPatchType) over Update to reduce conflicts","Fix invalid object fields flagged by the API server before retrying"],"exampleFix":"// before\nupdated, err := client.Update(ctx, obj, metav1.UpdateOptions{})\n// after\nupdated, err := client.Update(ctx, obj, metav1.UpdateOptions{})\nif err != nil {\n\tif apierrors.IsConflict(err) {\n\t\t// re-fetch obj, reapply change, retry with backoff\n\t}\n\treturn updated, err\n}","handlingStrategy":"retry","validationCode":"if obj.GetNamespace() == \"\" && requiresNamespace(gvk) {\n\treturn fmt.Errorf(\"pre-check: object %s needs a namespace before update\", gvk.Kind)\n}","typeGuard":"func isUpdateConflict(err error) bool {\n\treturn apierrors.IsConflict(errors.Unwrap(err))\n}","tryCatchPattern":"err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {\n\tfresh, err := client.Get(ctx, gvk, nn)\n\tif err != nil {\n\t\treturn err\n\t}\n\tapplyChanges(fresh)\n\t_, err = client.Update(ctx, fresh, metav1.UpdateOptions{})\n\treturn err\n})","preventionTips":["Always retry on conflict by re-fetching and re-applying changes","Prefer server-side apply to avoid resourceVersion churn","Avoid multiple concurrent writers updating the same object","Validate object fields before Update to avoid 422 rejections"],"tags":["kubernetes","update","conflict"],"backgroundTag":"kubernetes-update-conflict","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}