{"record":{"id":"018da3a99b4c2b85","repo":"theonedev/onedev","slug":"failed-to-create-kind-name-resource-still","errorCode":null,"errorMessage":"Failed to create ${kind} '${name}': resource still exists after deletion","messagePattern":"Failed to create (.+?) '(.+?)': resource still exists after deletion","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/util/KubernetesUtils.java","lineNumber":690,"sourceCode":"\t\t\tString kind = ((String) resourceDef.get(\"kind\")).toLowerCase();\n\t\t\tString name = (String) metadata.get(\"name\");\n\t\t\tString namespace = (String) metadata.get(\"namespace\");\n\n\t\t\tdeleteResource(kubectlFactory, kind, name, namespace, true, taskLogger);\n\n\t\t\tif (kind.equals(\"pod\") && namespace != null) {\n\t\t\t\twhile (resourceExists(kubectlFactory, kind, name, namespace, taskLogger)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tThread.sleep(1000);\n\t\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\t\tthrow new RuntimeException(e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tString retryResourceName = tryCreateResource(kubectlFactory, file, taskLogger);\n\t\t\tif (retryResourceName == null)\n\t\t\t\tthrow new ExplicitException(\"Failed to create \" + kind + \" '\" + name + \"': resource still exists after deletion\");\n\t\t\treturn retryResourceName;\n\t\t} finally {\n\t\t\tif (file != null)\n\t\t\t\tfile.delete();\n\t\t}\n\t}\n\n\t@Nullable\n\tprivate static String tryCreateResource(Supplier<Commandline> kubectlFactory, File yamlFile,\n\t\t\tTaskLogger taskLogger) {\n\t\tAtomicBoolean alreadyExists = new AtomicBoolean(false);\n\t\tAtomicReference<String> resourceNameRef = new AtomicReference<>(null);\n\t\tCommandline kubectl = kubectlFactory.get();\n\t\tkubectl.addArgs(\"create\", \"-f\", yamlFile.getAbsolutePath(), \"-o\", \"jsonpath={.metadata.name}\");\n\t\tvar result = kubectl.execute(new LineConsumer() {\n\n\t\t\t@Override\n\t\t\tpublic void consume(String line) {","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/util/KubernetesUtils.java#L672-L708","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nthrow new ExplicitException(\"Failed to create \" + kind + \" '\" + name + \"': resource still exists after deletion\");\n// after\n// operator-side fix: verify deletion actually completes before retrying\nkubectl delete <kind> <name> --wait=true --timeout=60s\nkubectl patch <kind> <name> -p '{\"metadata\":{\"finalizers\":[]}}' --type=merge   # only if stuck in Terminating","handlingStrategy":"validation","validationCode":"kubectl get <kind> <name> -o jsonpath='{.metadata.deletionTimestamp}'  # empty means not deleting; check finalizers too","typeGuard":null,"tryCatchPattern":"try {\n    KubernetesUtils.createResource(...);\n} catch (ExplicitException e) {\n    if (e.getMessage().contains(\"still exists after deletion\")) {\n        // manually remove finalizers / stale object, then retry\n    }\n}","preventionTips":["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)"],"tags":["kubernetes","resource-conflict","finalizers","kubectl"],"backgroundTag":"file-already-exists","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}