{"record":{"id":"8033c524d3ed940a","repo":"jenkinsci/jenkins","slug":"failed-to-delete-0","errorCode":null,"errorMessage":"Failed to delete {0}","messagePattern":"Failed to delete (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/hudson/PluginWrapper.java","lineNumber":775,"sourceCode":"    public void releaseClassLoader() {\n        if (classLoader instanceof Closeable)\n            try {\n                ((Closeable) classLoader).close();\n            } catch (IOException e) {\n                LOGGER.log(WARNING, \"Failed to shut down classloader\", e);\n            }\n    }\n\n    /**\n     * Enables this plugin next time Jenkins runs.\n     */\n    public void enable() throws IOException {\n        if (!disableFile.exists()) {\n            LOGGER.log(Level.FINEST, \"Plugin {0} has been already enabled. Skipping the enable() operation\", getShortName());\n            return;\n        }\n        if (!disableFile.delete())\n            throw new IOException(\"Failed to delete \" + disableFile);\n    }\n\n    /**\n     * Disables this plugin next time Jenkins runs. As it doesn't check anything, it's recommended to use the method\n     * {@link #disable(PluginDisableStrategy)}\n     * @deprecated use {@link #disable(PluginDisableStrategy)}\n     */\n    @Deprecated //see https://issues.jenkins.io/browse/JENKINS-27177\n    public void disable() throws IOException {\n        disableWithoutCheck();\n    }\n\n    /**\n     * Disable a plugin wihout checking any dependency. Only add the disable file.\n     */\n    private void disableWithoutCheck() throws IOException {\n        try (OutputStream os = Files.newOutputStream(disableFile.toPath())) {\n            // creates an empty file","sourceCodeStart":757,"sourceCodeEnd":793,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/core/src/main/java/hudson/PluginWrapper.java#L757-L793","documentation":"IOException thrown by PluginWrapper.enable() when disableFile.delete() returns false — the disable marker file (.disable) exists but could not be deleted, preventing the plugin from being enabled on next restart. Common causes: insufficient filesystem permissions, the file is locked by another process, or the parent directory is read-only.","triggerScenarios":"Calling plugin.enable() when the .disable file exists but File.delete() fails (returns false) due to permissions, locks, or filesystem errors.","commonSituations":"Jenkins running as a user without write access to the plugins directory (common in Docker with wrong UID/GID mapping), the .disable file locked by an antivirus or backup process on Windows, or a read-only mount for the plugins directory.","solutions":["Verify the Jenkins process has write/delete permission on the plugins directory and the .disable file.","On Windows, close any process locking the file (antivirus, indexer, backup).","In Docker, ensure the container UID matches the plugins directory owner.","Manually delete the .disable file and retry."],"exampleFix":"// before\nwrapper.enable();\n\n// after — check permissions and handle failure\nFile disableFile = new File(wrapper.getShortName() + \".jpi.disable\");\nif (disableFile.exists() && !disableFile.delete()) {\n    disableFile.setWritable(true, false);\n    if (!disableFile.delete()) {\n        throw new IOException(\"Cannot remove .disable file; check permissions: \" + disableFile);\n    }\n}","handlingStrategy":"validation","validationCode":"if (disableFile.exists() && !disableFile.canWrite()) {\n    disableFile.setWritable(true, false);\n}\nif (disableFile.exists() && !disableFile.delete()) {\n    throw new IOException(\"Cannot delete .disable file; check permissions: \" + disableFile);\n}","typeGuard":null,"tryCatchPattern":"try {\n    wrapper.enable();\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Failed to delete\")) {\n        File disableFile = new File(wrapper.getShortName() + \".jpi.disable\");\n        disableFile.setWritable(true, false);\n        if (!disableFile.delete()) {\n            throw new IOException(\"Permission denied on plugins directory; cannot enable plugin.\", e);\n        }\n    } else {\n        throw e;\n    }\n}","preventionTips":["Ensure the Jenkins process UID/GID has write access to the plugins directory.","In Docker, match the container user to the plugins directory owner.","On Windows, exclude the Jenkins home from antivirus real-time scanning."],"tags":["plugin-wrapper","filesystem","permissions","enable-disable"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}