jenkinsci/jenkins · error · IOException
Failed to delete {0}
Error message
Failed to delete {0} What it means
Thrown during folder/group deletion when iterating child items: if i.delete() throws AbortException, it is re-thrown as a new AbortException with 'Failed to delete <child> : <cause>'; if it throws a plain IOException, it is wrapped as IOException('Failed to delete <child>', cause). This surfaces which child item failed during a recursive folder delete.
Source
Thrown at core/src/main/java/hudson/model/AbstractItem.java:811
try {
// if a build is in progress. Cancel it.
if (responsibleForAbortingBuilds || ownsRegistration) {
ItemDeletion.cancelBuildsInProgress(this);
}
if (this instanceof ItemGroup) {
// delete individual items first
// (disregard whether they would be deletable in isolation)
// JENKINS-34939: do not hold the monitor on this folder while deleting them
// (thus we cannot do this inside performDelete)
try (ACLContext oldContext = ACL.as2(ACL.SYSTEM2)) {
for (Item i : ((ItemGroup<?>) this).getItems(TopLevelItem.class::isInstance)) {
try {
i.delete();
} catch (AbortException e) {
throw (AbortException) new AbortException(
"Failed to delete " + i.getFullDisplayName() + " : " + e.getMessage()).initCause(e);
} catch (IOException e) {
throw new IOException("Failed to delete " + i.getFullDisplayName(), e);
}
}
}
}
synchronized (this) { // could just make performDelete synchronized but overriders might not honor that
performDelete();
} // JENKINS-19446: leave synch block, but JENKINS-22001: still notify synchronously
} finally {
if (ownsRegistration) {
ItemDeletion.deregister(this);
}
}
SaveableListener.fireOnDeleted(this, getConfigFile());
getParent().onDeleted(AbstractItem.this);
Jenkins.get().rebuildDependencyGraphAsync();
}
/**View on GitHub (pinned to 2e228ff40b)
Solutions
- Read the cause exception to identify which child failed and why (the child name is in the message)
- Cancel builds on or fix the specific child item that failed, then retry the folder delete
- Check DELETE permission on all children (the loop runs as SYSTEM via ACLContext, but plugin guards may still fail)
- If a plugin's performDelete is the culprit, update or disable that plugin
Defensive patterns
Strategy: try-catch
Try / catch
try {
folder.delete();
} catch (IOException | AbortException e) {
if (e.getMessage().startsWith("Failed to delete")) {
// a child item failed; inspect cause and fix the specific child, then retry
}
throw e;
} Prevention
- Before deleting a folder, cancel builds on all children and verify no locks
- Ensure all children are deletable (permissions, no running builds)
- Inspect the wrapped cause to find the failing child and plugin
When it happens
Trigger: delete() is called on an ItemGroup; the loop over getItems(TopLevelItem.class::isInstance) calls i.delete() on each child; a child's performDelete or its own delete throws.
Common situations: A child job has a running build that cannot be cancelled; a child item's config or workspace is locked/on a read-only filesystem; a plugin's DeleteListener or performDelete override throws; permission issues on a specific child.
Related errors
- {0} is currently being deleted
- Unknown ItemGroup
- Can't create job from CLI in
- Unknown ItemGroup
- Can't create job from CLI in
AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14).
Data as JSON: /api/errors/24e3ec5b8d7d7a18.
Report an issue: GitHub.