{"record":{"id":"969bfbb630222da0","repo":"derailed/k9s","slug":"user-is-not-authorized-to-delete-s-969bfb","errorCode":null,"errorMessage":"user is not authorized to delete %s","messagePattern":"user is not authorized to delete (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/dao/workload.go","lineNumber":51,"sourceCode":"\tclient.StsGVR,\n\tclient.DpGVR,\n\tclient.RsGVR,\n}\n\n// Workload tracks a select set of resources in a given namespace.\ntype Workload struct {\n\tTable\n}\n\nfunc (w *Workload) Delete(ctx context.Context, path string, propagation *metav1.DeletionPropagation, grace Grace) error {\n\tgvr, _ := ctx.Value(internal.KeyGVR).(*client.GVR)\n\tns, n := client.Namespaced(path)\n\tauth, err := w.Client().CanI(ns, gvr, n, []string{client.DeleteVerb})\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !auth {\n\t\treturn fmt.Errorf(\"user is not authorized to delete %s\", path)\n\t}\n\n\tvar gracePeriod *int64\n\tif grace != DefaultGrace {\n\t\tgracePeriod = (*int64)(&grace)\n\t}\n\topts := metav1.DeleteOptions{\n\t\tPropagationPolicy:  propagation,\n\t\tGracePeriodSeconds: gracePeriod,\n\t}\n\n\tctx, cancel := context.WithTimeout(ctx, w.Client().Config().CallTimeout())\n\tdefer cancel()\n\n\td, err := w.Client().DynDial()\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/dao/workload.go#L33-L69","documentation":"Workload.Delete runs a SelfSubjectAccessReview (Client().CanI) for the delete verb on the workload's GVR before issuing the delete. If the review says not-allowed, the delete is refused client-side and the API server is never called.","triggerScenarios":"Deleting any workload through Workload.Delete with a kubeconfig user whose Role/ClusterRole lacks the delete verb for that resource in that namespace (e.g. view-only roles, CI tokens, impersonated under-privileged users).","commonSituations":"Read-only viewer bindings in production clusters; service accounts used by pipelines that can list but not delete; assuming a restricted identity via k9s --as-user flag.","solutions":["Confirm with kubectl auth can-i delete <resource>.<group> -n <ns> (same user)","Add verbs: [\"delete\"] (and deletecollection if bulk deletes are needed) for that resource to the bound Role/ClusterRole","Apply the RoleBinding or switch context to a user with delete rights","If RBAC cannot change, delete from an authorized context: kubectl delete <resource> <name> -n <ns>"],"exampleFix":"# before\nverbs: [\"get\", \"list\", \"watch\"]\n# after\nverbs: [\"get\", \"list\", \"watch\", \"delete\"]","handlingStrategy":"validation","validationCode":"allowed, err := k8sClient.CanI(ns, gvr, name, []string{\"delete\"})\nif err != nil { return err }\nif !allowed {\n    return fmt.Errorf(\"missing delete on %s in %s — grant it or use an authorized context\", gvr, ns)\n}","typeGuard":null,"tryCatchPattern":"if err := w.Delete(ctx, path, propagation, grace); err != nil {\n    if strings.Contains(err.Error(), \"not authorized to delete\") {\n        return confirmAndRetryWithPrivilegedContext(path) // or abort with an RBAC hint\n    }\n    return err\n}","preventionTips":["Gate delete buttons/actions on a CanI pre-check so unauthorized users never trigger the call","Document required verbs per role for teams using restricted kubeconfigs"],"tags":["kubernetes","rbac","delete","authorization","k9s"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}