{"record":{"id":"f10ee937a12618f2","repo":"jenkinsci/jenkins","slug":"failed-to-load-it-is-not-a-file","errorCode":null,"errorMessage":"Failed to load {}. It is not a file","messagePattern":"Failed to load (.+?)\\. It is not a file","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/hudson/ClassicPluginStrategy.java","lineNumber":100,"sourceCode":"    private static final Logger LOGGER = Logger.getLogger(ClassicPluginStrategy.class.getName());\n\n    /**\n     * Filter for jar files.\n     */\n    private static final FilenameFilter JAR_FILTER = (dir, name) -> name.endsWith(\".jar\");\n\n    private final PluginManager pluginManager;\n\n    public ClassicPluginStrategy(PluginManager pluginManager) {\n        this.pluginManager = pluginManager;\n    }\n\n    @Override public String getShortName(File archive) throws IOException {\n        Manifest manifest;\n        if (!archive.exists()) {\n            throw new FileNotFoundException(\"Failed to load \" + archive + \". The file does not exist\");\n        } else if (!archive.isFile()) {\n            throw new FileNotFoundException(\"Failed to load \" + archive + \". It is not a file\");\n        }\n\n        if (isLinked(archive)) {\n            manifest = loadLinkedManifest(archive);\n        } else {\n            try (JarFile jf = new JarFile(archive, false)) {\n                manifest = jf.getManifest();\n            } catch (IOException ex) {\n                // Mention file name in the exception\n                throw new IOException(\"Failed to load \" + archive, ex);\n            }\n        }\n        return PluginWrapper.computeShortName(manifest, archive.getName());\n    }\n\n    private static boolean isLinked(File archive) {\n        return archive.getName().endsWith(\".hpl\") || archive.getName().endsWith(\".jpl\");\n    }","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/jenkinsci/jenkins/blob/2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc/core/src/main/java/hudson/ClassicPluginStrategy.java#L82-L118","documentation":"FileNotFoundException thrown by ClassicPluginStrategy.getShortName when the archive path exists but archive.isFile() is false (it is a directory, a device, or otherwise not a regular file). Jenkins expects a single .jpi/.hpi file to read a manifest from.","triggerScenarios":"The path resolves to a directory (e.g. an already-exploded plugin passed where a packed archive is required), a broken symlink, or a special file.","commonSituations":"An expanded plugin directory is passed as an archive; a symlink that target-checks as non-file; leftover directory from a partial extraction.","solutions":["Pass the packed .jpi/.hpi archive, not its expanded directory, to getShortName/createPluginWrapper.","If a symlink is involved, ensure its target is a regular file.","Clean up partially extracted plugin directories so only valid archives remain."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"File archive = new File(path);\nif (!archive.isFile()) {\n    throw new IllegalArgumentException(archive + \" is not a regular file; pass a .jpi/.hpi archive\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    strategy.getShortName(archive);\n} catch (FileNotFoundException e) {\n    if (e.getMessage().contains(\"not a file\")) {\n        // point the caller at the packed archive instead of the directory\n    }\n}","preventionTips":["Pass packed plugin archives (.jpi/.hpi) to load operations, not expanded directories.","Ensure symlinks resolve to regular files.","Clean partially extracted directories from the plugins folder."],"tags":["jenkins","plugin-loading","filesystem","invalid-type"],"backgroundTag":null,"analyzedSha":"2e228ff40b14dbc8b14ffbc6edf0e4383cf744fc","analyzedAt":"2026-08-14T07:07:15.274Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}