jenkinsci/jenkins · error · IOException

No such file: {}

Error message

No such file: {}

What it means

Thrown by parseClassPath while reading the Class-Path attribute from a plugin archive's JAR manifest. Jenkins resolves each entry relative to the archive parent; entries without a wildcard must exist on disk, otherwise loading aborts with this IOException. This mirrors the JAR Class-Path spec where referenced jars must sit beside the referencing jar.

Source

Thrown at core/src/main/java/hudson/ClassicPluginStrategy.java:459

    }

    private static void parseClassPath(Manifest manifest, File archive, List<File> paths, String attributeName, String separator) throws IOException {
        String classPath = manifest.getMainAttributes().getValue(attributeName);
        if (classPath == null) return; // attribute not found
        for (String s : classPath.split(separator)) {
            File file = resolve(archive, s);
            if (file.getName().contains("*")) {
                // handle wildcard
                FileSet fs = new FileSet();
                File dir = file.getParentFile();
                fs.setDir(dir);
                fs.setIncludes(file.getName());
                for (String included : fs.getDirectoryScanner(new Project()).getIncludedFiles()) {
                    paths.add(new File(dir, included));
                }
            } else {
                if (!file.exists())
                    throw new IOException("No such file: " + file);
                paths.add(file);
            }
        }
    }

    /**
     * Explodes the plugin into a directory, if necessary.
     */
    private static void explode(File archive, File destDir) throws IOException {
        Util.createDirectories(Util.fileToPath(destDir));

        // timestamp check
        File explodeTime = new File(destDir, ".timestamp2");
        if (explodeTime.exists() && explodeTime.lastModified() == archive.lastModified())
            return; // no need to expand

        // delete the contents so that old files won't interfere with new files
        Util.deleteRecursive(destDir);

View on GitHub (pinned to 2e228ff40b)

Solutions

  1. Inspect the plugin archive's MANIFEST.MF Class-Path attribute and check each referenced path exists relative to the archive.
  2. Rebuild the plugin with the build tool so the manifest Class-Path is generated correctly.
  3. If a referenced jar is genuinely optional, use a wildcard entry (name contains *) instead of a literal path.
  4. Reinstall the plugin from a known-good source so all sibling files are present.

Example fix

// Manifest entry referencing a missing sibling
// before: Class-Path: libs/missing.jar
// after:  Class-Path: libs/present.jar   (ensure the file ships beside the plugin)
Defensive patterns

Strategy: validation

Validate before calling

Manifest m = new JarFile(archive).getManifest();
String cp = m.getMainAttributes().getValue(Attributes.Name.CLASS_PATH);
if (cp != null) {
    for (String entry : cp.split(" ")) {
        File resolved = new File(archive.getParentFile(), entry);
        if (!resolved.getName().contains("*") && !resolved.exists()) {
            throw new IllegalStateException("Missing Class-Path entry: " + resolved);
        }
    }
}

Type guard

null

Try / catch

try {
    strategy.load(wrapper);
} catch (IOException e) {
    if (e.getMessage().startsWith("No such file:")) { /* log and skip the broken manifest entry */ }
    else throw e;
}

Prevention

When it happens

Trigger: A plugin's MANIFEST.MF contains a Class-Path entry (or a custom attribute parsed via parseClassPath) whose non-wildcard path does not resolve to an existing file; the referenced file was deleted, never packaged, or the path is absolute and points off-host.

Common situations: Hand-edited manifest with a wrong relative path; build repackaged the plugin and dropped a sibling jar; plugin moved out of its expected directory so sibling libs are gone; absolute Class-Path entry pointing to a path that only exists on the build machine.

Related errors


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