kubernetes/kubernetes · warning
unable to delete PodCertificateRequest %q: %w
Error message
unable to delete PodCertificateRequest %q: %w
What it means
Returned by the PodCertificateRequest cleaner controller's handle function when deleting a PCR that is older than the configured threshold fails. Unlike the CSR cleaner, this code properly handles NotFound (line 100-102) before wrapping the error, so only genuine deletion failures (permission, API errors) produce this error. The %w verb preserves the error chain for unwrapping.
Source
Thrown at pkg/controller/certificates/cleaner/pcrcleaner.go:104
}
func (c PCRCleanerController) handle(ctx context.Context, pcr *certsv1.PodCertificateRequest) error {
if c.clock.Now().Before(pcr.ObjectMeta.CreationTimestamp.Time.Add(c.threshold)) {
return nil
}
opts := metav1.DeleteOptions{
Preconditions: &metav1.Preconditions{
UID: ptr.To(pcr.ObjectMeta.UID),
},
}
err := c.client.CertificatesV1().PodCertificateRequests(pcr.ObjectMeta.Namespace).Delete(ctx, pcr.ObjectMeta.Name, opts)
if k8serrors.IsNotFound(err) {
// This is OK, we don't care if someone else already deleted it.
return nil
} else if err != nil {
return fmt.Errorf("unable to delete PodCertificateRequest %q: %w", pcr.ObjectMeta.Namespace+"/"+pcr.ObjectMeta.Name, err)
}
return nil
}
View on GitHub (pinned to 94c1367642)
Solutions
- Check the wrapped error — if it is a Conflict (apierrors.IsConflict), the UID precondition failed because the PCR was replaced; this is benign.
- Verify the controller manager's ClusterRole includes 'delete' on 'podcertificaterequests'.
- Ensure the PodCertificateRequests feature gate is enabled and the API is available in the cluster version.
- If errors persist, check API server health and the PCR API registration.
Defensive patterns
Strategy: retry
Try / catch
// The PCR cleaner already handles NotFound. If building custom cleanup:
if err := client.CertificatesV1().PodCertificateRequests(ns).Delete(ctx, name, opts); err != nil {
if k8serrors.IsNotFound(err) {
return nil // already cleaned
}
if k8serrors.IsConflict(err) {
// UID precondition failed — PCR was replaced
return nil
}
return fmt.Errorf("unable to delete PodCertificateRequest %q: %w", ns+"/"+name, err)
} Prevention
- Ensure the controller manager's ClusterRole includes 'delete' on 'podcertificaterequests'.
- Handle Conflict (UID mismatch) errors gracefully — they indicate the resource was replaced.
- Verify the PodCertificateRequests feature gate is enabled in the cluster.
- Monitor cleaner error rates; persistent non-Conflict errors indicate RBAC issues.
When it happens
Trigger: The cleaner identifies a PodCertificateRequest older than the threshold and calls client.CertificatesV1().PodCertificateRequests(namespace).Delete(ctx, name, opts) with a UID precondition. The delete fails with a non-NotFound error: permission denied, API server error, or UID mismatch (Conflict, since the PCR was recreated with a different UID).
Common situations: The controller manager lacks RBAC permission to delete podcertificaterequests. The PCR was deleted and a new one with the same name but different UID was created (UID precondition Conflict). API server connectivity issues during the cleanup polling interval.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- unable to delete CSR %q: %v
- error updating approval for csr: %v
- must have cluster-admin privileges to use the aggregationRul
- user %q (groups=%q) is attempting to grant RBAC permissions
- cannot specify default and per controller certs at the same
AI-assisted analysis of kubernetes/kubernetes@94c1367642 (2026-08-08).
Data as JSON: /api/errors/14917bc10b62834d.
Report an issue: GitHub.