GoogleContainerTools/skaffold · error
%d resources failed to complete their deletion before a new
Error message
%d resources failed to complete their deletion before a new deployment: %s
What it means
Before applying new manifests, the kubectl deployer waits for previously deleted resources to actually disappear, polling `kubectl get -f - --ignore-not-found -ojson`. If the context deadline expires while resources still exist, it reports how many resources and which ones failed to delete in time. This prevents applying a new deployment on top of still-terminating resources.
Source
Thrown at pkg/skaffold/deploy/kubectl/cli.go:146
} `json:"items"`
}
// WaitForDeletions waits for resource marked for deletion to complete their deletion.
func (c *CLI) WaitForDeletions(ctx context.Context, out io.Writer, manifests manifest.ManifestList) error {
if !c.waitForDeletions.Enabled {
return nil
}
ctx, cancel := context.WithTimeout(ctx, c.waitForDeletions.Max)
defer cancel()
previousList := ""
previousCount := 0
for {
select {
case <-ctx.Done():
return waitForDeletionErr(fmt.Errorf("%d resources failed to complete their deletion before a new deployment: %s", previousCount, previousList))
default:
// List resources in json format.
buf, err := c.RunOutInput(ctx, manifests.Reader(), "get", c.args(nil, "-f", "-", "--ignore-not-found", "-ojson")...)
if err != nil {
return waitForDeletionErr(err)
}
// No resource found.
if len(buf) == 0 {
return nil
}
// Find which ones are marked for deletion. They have a `metadata.deletionTimestamp` field.
var result getResult
if err := json.Unmarshal(buf, &result); err != nil {
return waitForDeletionErr(err)
}
View on GitHub (pinned to a1189de023)
Solutions
- Inspect the listed resources: `kubectl get <resources>` and remove blocking finalizers (`kubectl patch <res> -p '{"metadata":{"finalizers":[]}}' --type=merge`).
- Delete the parent namespace if it is stuck Terminating and re-create it.
- Increase the deletion wait timeout / check for slow storage teardown (e.g. AWS EBS volume detach).
- Check for validating webhook outages that block DELETE requests.
Example fix
// before: stuck resource with finalizer
kubectl get pod mypod -o jsonpath='{.metadata.finalizers}'
// after
kubectl patch pod mypod -p '{"metadata":{"finalizers":null}}' --type=merge Defensive patterns
Strategy: retry
Validate before calling
// Check for stuck resources before triggering a new deployment
out, _ := exec.Command("kubectl", "get", "-f", file, "--ignore-not-found", "-ojson").Output()
if len(strings.TrimSpace(string(out))) > 0 && strings.Contains(string(out), "Terminating") {
return fmt.Errorf("resources still terminating; clear finalizers first")
} Try / catch
if err := cli.WaitForDeletions(ctx, out, manifests); err != nil {
var wd waitForDeletionErr
if errors.As(err, &wd) {
// list stuck resources, clear finalizers, then retry
}
} Prevention
- Monitor for resources stuck in Terminating (finalizers) before redeploying
- Increase deletion wait timeout in slow-storage environments
- Keep validating webhooks highly available so DELETEs aren't blocked
- Clean up stuck namespaces proactively
When it happens
Trigger: The WaitForDeletions polling loop hits ctx.Done() while previousCount > 0 — resources stuck Terminating (finalizers) or deletion very slow for the listed resources (previousList names them).
Common situations: Namespaces stuck Terminating due to finalizers; PVCs or webhooks blocking pod deletion; very slow cluster; too-short skaffold status/deletion timeout.
Related errors
- %q running k8s job timed out after : %v
- kubectl delete: %w
- kubectl apply: %w
- kubectl create: %w
- unable to connect to Kubernetes: %w
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/6d3af109e29a7e8b.
Report an issue: GitHub.