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

  1. Read the cause exception to identify which child failed and why (the child name is in the message)
  2. Cancel builds on or fix the specific child item that failed, then retry the folder delete
  3. Check DELETE permission on all children (the loop runs as SYSTEM via ACLContext, but plugin guards may still fail)
  4. 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

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


AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14). Data as JSON: /api/errors/24e3ec5b8d7d7a18. Report an issue: GitHub.