quarkusio/quarkus · critical · IOException

Unsupported AOT cache version: expected ${VERSION} but got $

Error message

Unsupported AOT cache version: expected ${VERSION} but got ${version}

What it means

After the magic check, AotSerializedApplication.read() reads a version integer that must match the VERSION constant of the running runner. A mismatch means the cache was produced by a different Quarkus version than the one reading it, so the binary layout cannot be trusted and an IOException is thrown with both version numbers.

Source

Thrown at independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/AotSerializedApplication.java:164

    /**
     * Reads cached resources from an input stream.
     *
     * @param in the input stream to read from
     * @return an AotSerializedApplication containing the main class and cached resources
     * @throws IOException if an I/O error occurs or the format is invalid
     */
    public static AotSerializedApplication read(InputStream in) throws IOException {
        try (DataInputStream data = new DataInputStream(in)) {
            int magic = data.readInt();
            if (magic != MAGIC) {
                throw new IOException("Invalid magic number in AOT cache file: expected 0x"
                        + Integer.toHexString(MAGIC) + " but got 0x" + Integer.toHexString(magic));
            }

            int version = data.readInt();
            if (version != VERSION) {
                throw new IOException("Unsupported AOT cache version: expected " + VERSION + " but got " + version);
            }

            String mainClass = data.readUTF();

            // Read tracked directories
            int fullyIndexedDirectoryCount = data.readInt();
            Set<String> fullyIndexedDirectories = new HashSet<>((int) Math.ceil(fullyIndexedDirectoryCount / 0.75f));
            for (int i = 0; i < fullyIndexedDirectoryCount; i++) {
                fullyIndexedDirectories.add(data.readUTF());
            }

            // Read directory contents
            int fullyIndexedResourceCount = data.readInt();
            Set<String> fullyIndexedResources = new HashSet<>((int) Math.ceil(fullyIndexedResourceCount / 0.75f));
            for (int i = 0; i < fullyIndexedResourceCount; i++) {
                fullyIndexedResources.add(data.readUTF());
            }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Rebuild the application (mvn clean package) so the cache version matches the runner version.
  2. Clear stale Docker/CI layer caches so the old quarkus-application.dat is not reused.
  3. Ensure the runner jar and the cache come from the same Quarkus version.

Example fix

// before: reusing old build dir after Quarkus upgrade
java -jar target/quarkus-app/quarkus-run.jar // stale cache

// after
mvn clean package && java -jar target/quarkus-app/quarkus-run.jar
Defensive patterns

Strategy: fallback

Validate before calling

Path cache = Paths.get("target/quarkus-app/quarkus-application.dat");
long lastBuilt = Files.getLastModifiedTime(cache).toMillis();
long runnerBuilt = Files.getLastModifiedTime(Paths.get("target/quarkus-app/quarkus-run.jar")).toMillis();
if (Math.abs(lastBuilt - runnerBuilt) > 60_000) {
    System.err.println("WARNING: cache and runner timestamps differ; rebuild required");
}

Try / catch

try {
    app = AotSerializedApplication.read(in);
} catch (IOException e) {
    if (e.getMessage().startsWith("Unsupported AOT cache version")) {
        throw new IllegalStateException("Cache built by different Quarkus version; run mvn clean package", e);
    } throw e;
}

Prevention

When it happens

Trigger: Reading a quarkus-application.dat generated by a different Quarkus version than the AotSerializedApplication class performing the read (upgraded runner jar with old cache, or downgraded runner with newer cache).

Common situations: Upgrading Quarkus but reusing a previously built quarkus-app directory or Docker layer cache; mixing runner and app artifacts from different builds.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/de363f70a1bf83e1. Report an issue: GitHub.