{"record":{"id":"35ebdc02d952b621","repo":"kubernetes/kops","slug":"error-patching-object-w","errorCode":null,"errorMessage":"error patching object: %w","messagePattern":"error patching object: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/applylib/applyset/unstructuredclient.go","lineNumber":89,"sourceCode":"\t\treturn c.client.Resource(gvr), nil\n\n\tdefault:\n\t\t// Internal error ... this is panic-level\n\t\treturn nil, fmt.Errorf(\"unknown scope for gvk %s: %q\", gvk, restMapping.Scope.Name())\n\t}\n}\n\n// Patch performs a Patch operation, used for server-side apply and client-side patch.\nfunc (c *UnstructuredClient) Patch(ctx context.Context, gvk schema.GroupVersionKind, nn types.NamespacedName, patchType types.PatchType, data []byte, opt metav1.PatchOptions) (*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\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}","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/applylib/applyset/unstructuredclient.go#L71-L107","documentation":"Patch wraps any error returned by the underlying dynamic resource client's Patch call with this message. It is a generic wrapper: the root cause (network, RBAC, conflict, validation, or the scope errors from dynamicResource) is in the wrapped error chain via %w.","triggerScenarios":"Calling UnstructuredClient.Patch (used for server-side apply and client-side patch) where dynamicResource.Patch fails: API server errors (409 Conflict, 422 Unprocessable, 403 Forbidden), network failures, or an empty-namespace/scope error from building the client.","commonSituations":"Server-side apply conflicts when field managers changed the object; RBAC denying patch on the resource; patching an object that was deleted concurrently; missing namespace triggering the dynamicResource scope error wrapped here.","solutions":["Unwrap with errors.Unwrap / %v of err to read the real API status (use apierrors to inspect StatusCause/Reason)","Retry on conflict (409) with backoff and a fresh copy of the object","Check RBAC rules for patch permission on the resource in the namespace","If server-side apply conflicts persist, inspect managedFields and adopt/steal field ownership"],"exampleFix":"// before\npatched, err := client.Patch(ctx, gvk, nn, types.ApplyPatchType, data, opts)\n// after\npatched, err := client.Patch(ctx, gvk, nn, types.ApplyPatchType, data, opts)\nif err != nil {\n\tif apierrors.IsConflict(err) {\n\t\t// retry with backoff / re-fetch object\n\t}\n\tif apierrors.IsForbidden(err) {\n\t\t// check RBAC\n\t}\n\treturn patched, err\n}","handlingStrategy":"try-catch","validationCode":"if nn.Namespace == \"\" && requiresNamespace(gvk) {\n\treturn fmt.Errorf(\"pre-check: namespace required to patch %s\", gvk)\n}","typeGuard":"func isRetryablePatchErr(err error) bool {\n\treturn apierrors.IsConflict(err) || apierrors.IsTimeout(err) || apierrors.IsServerTimeout(err)\n}","tryCatchPattern":"patched, err := client.Patch(ctx, gvk, nn, patchType, data, opt)\nif err != nil {\n\tswitch {\n\tcase apierrors.IsConflict(errors.Unwrap(err)):\n\t\t// retry with backoff and fresh resourceVersion\n\tcase apierrors.IsForbidden(errors.Unwrap(err)):\n\t\t// check RBAC patch permissions\n\tdefault:\n\t\treturn err\n\t}\n}","preventionTips":["Use retry/backoff for conflict errors before surfacing failure","Inspect managedFields when server-side apply conflicts occur","Verify RBAC patch rights for all applied kinds beforehand","Prefer server-side apply (ApplyPatchType) over manual patches"],"tags":["kubernetes","patch","api-server"],"backgroundTag":"kubernetes-patch-failed","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"}