theonedev/onedev · error · ExplicitException
Failed to create ${kind} '${name}': resource still exists af
Error message
Failed to create ${kind} '${name}': resource still exists after deletion What it means
When creating a Kubernetes resource via kubectl, if the initial create fails because the resource already exists, the code deletes it and retries creation via tryCreateResource. If the retry still returns null (resource still present), it means the delete didn't take effect (e.g. finalizers blocking deletion) and this ExplicitException is thrown.
Source
Thrown at server-core/src/main/java/io/onedev/server/util/KubernetesUtils.java:690
String kind = ((String) resourceDef.get("kind")).toLowerCase();
String name = (String) metadata.get("name");
String namespace = (String) metadata.get("namespace");
deleteResource(kubectlFactory, kind, name, namespace, true, taskLogger);
if (kind.equals("pod") && namespace != null) {
while (resourceExists(kubectlFactory, kind, name, namespace, taskLogger)) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
String retryResourceName = tryCreateResource(kubectlFactory, file, taskLogger);
if (retryResourceName == null)
throw new ExplicitException("Failed to create " + kind + " '" + name + "': resource still exists after deletion");
return retryResourceName;
} finally {
if (file != null)
file.delete();
}
}
@Nullable
private static String tryCreateResource(Supplier<Commandline> kubectlFactory, File yamlFile,
TaskLogger taskLogger) {
AtomicBoolean alreadyExists = new AtomicBoolean(false);
AtomicReference<String> resourceNameRef = new AtomicReference<>(null);
Commandline kubectl = kubectlFactory.get();
kubectl.addArgs("create", "-f", yamlFile.getAbsolutePath(), "-o", "jsonpath={.metadata.name}");
var result = kubectl.execute(new LineConsumer() {
@Override
public void consume(String line) {View on GitHub (pinned to d44925c47c)
Solutions
- kubectl get <kind> <name> -o yaml to check for finalizers and Terminating state
- Remove blocking finalizers (kubectl patch <kind> <name> -p '{"metadata":{"finalizers":[]}}' --type=merge) or delete the stale object manually
- Ensure each build uses unique resource names (project/instance prefixes) to avoid collisions
- Check RBAC: the service account may lack delete permission so deletion never succeeded
Example fix
// before
throw new ExplicitException("Failed to create " + kind + " '" + name + "': resource still exists after deletion");
// after
// operator-side fix: verify deletion actually completes before retrying
kubectl delete <kind> <name> --wait=true --timeout=60s
kubectl patch <kind> <name> -p '{"metadata":{"finalizers":[]}}' --type=merge # only if stuck in Terminating Defensive patterns
Strategy: validation
Validate before calling
kubectl get <kind> <name> -o jsonpath='{.metadata.deletionTimestamp}' # empty means not deleting; check finalizers too Try / catch
try {
KubernetesUtils.createResource(...);
} catch (ExplicitException e) {
if (e.getMessage().contains("still exists after deletion")) {
// manually remove finalizers / stale object, then retry
}
} Prevention
- Use unique resource names per build (include build number) to avoid collisions
- Ensure the service account has delete permissions for all relevant kinds
- Periodically clean up stale resources stuck in Terminating
- Check that previous builds cleaned up their resources (deferred deletion hooks)
When it happens
Trigger: Calling KubernetesUtils resource-create helpers when a same-named resource (pod/service/secret etc.) already exists, and after deleting it and retrying the create, tryCreateResource still cannot create it — typically because the old object is stuck in Terminating state with finalizers or the delete failed silently.
Common situations: Leftover resources from a crashed previous build; PVCs or namespaces with kubernetes.io finalizers stuck in Terminating; stale resources from an aborted pipeline; name collisions between concurrent jobs.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- Shell not ready
- Unexpected end of pod watching
- No applicable provisioner discovered for current workspace.
- OneDev running inside kubernetes cluster does not support wo
- OneDev running inside kubernetes cluster does not support wo
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/018da3a99b4c2b85.
Report an issue: GitHub.