oracle/graal · error · IOException

The image file "{name}" is corrupted

Error message

The image file "{name}" is corrupted

What it means

BasicImageReader memory-maps a jimage file and validates that the mapped buffer is large enough for the header-declared index size. If memoryMap.capacity() < indexSize, the file's header claims an index larger than the file itself, so the file is truncated/corrupted and an IOException is thrown.

Source

Thrown at espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/jimage/BasicImageReader.java:86

            do {
                lastRead = channel.read(map);
            } while (lastRead >= 0 && map.hasRemaining());
        }

        int headerSize = ImageHeader.getHeaderSize();
        if (map.capacity() < headerSize) {
            throw new NotAnImageFile();
        }

        // Interpret the image file header
        header = readHeader(intBuffer(map, 0, headerSize));
        indexSize = header.getIndexSize();

        memoryMap = map.asReadOnlyBuffer();

        // Interpret the image index
        if (memoryMap.capacity() < indexSize) {
            throw new IOException("The image file \"" + name + "\" is corrupted");
        }
        redirect = intBuffer(memoryMap, header.getRedirectOffset(), header.getRedirectSize());
        offsets = intBuffer(memoryMap, header.getOffsetsOffset(), header.getOffsetsSize());
        locations = slice(memoryMap, header.getLocationsOffset(), header.getLocationsSize());
        strings = slice(memoryMap, header.getStringsOffset(), header.getStringsSize());

        stringsReader = new ImageStringsReader(strings);
        decompressor = new Decompressor();
    }

    public static final class NotAnImageFile extends IOException {
        static final long serialVersionUID = -3240111096036918189L;
    }

    public static BasicImageReader open(Path path) throws IOException {
        return new BasicImageReader(path, ByteOrder.nativeOrder());
    }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Verify the JDK/GraalVM installation: re-download and re-extract the JDK so lib/modules is intact.
  2. Point Espresso at a known-good java home (espresso.JavaHome) and retry.
  3. Compare file sizes/checksums of <java-home>/lib/modules against a reference installation.
  4. If a custom jimage is used, rebuild it with a current jimage tool so header index size matches content.
Defensive patterns

Strategy: validation

Validate before calling

// Sanity-check the image before opening
Path p = Path.of(javaHome, "lib", "modules");
long expected = referenceModulesSizeFor(jdkVersion);
if (Files.size(p) != expected) { /* reinstall JDK */ }

Try / catch

try {
    reader = new BasicImageReader(path);
} catch (IOException e) {
    if (e.getMessage().contains("corrupted")) { /* re-extract JDK, verify checksum */ }
}

Prevention

When it happens

Trigger: Opening a modules jimage file that was truncated by a partial download/install, modified by a broken tool, or is on a filesystem returning short mmaps; Espresso locating a jimage via -version or custom java home.

Common situations: Corrupted or partially-extracted GraalVM/JDK installation; jimage patched by build tooling that rewrote offsets inconsistently; network filesystems delivering inconsistent file length.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/cbe3c29f9c507e07. Report an issue: GitHub.