quarkusio/quarkus · error · RuntimeException
Wrong class path version
Error message
Wrong class path version
What it means
SerializedApplication.read deserializes the fast-jar application manifest that Quarkus generated at build time. After checking the magic number, it verifies the serialized class path VERSION constant; if the stream's version differs from the reader's expected VERSION, it throws 'Wrong class path version'. This protects against running an app root produced by an incompatible Quarkus build.
Source
Thrown at independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/SerializedApplication.java:138
data.writeShort(fullyIndexedResourcesToCPJarIndex.size());
for (Map.Entry<String, List<Integer>> entry : fullyIndexedResourcesToCPJarIndex.entrySet()) {
data.writeUTF(entry.getKey());
data.writeShort(entry.getValue().size());
for (Integer index : entry.getValue()) {
data.writeShort(index);
}
}
data.flush();
}
}
public static SerializedApplication read(InputStream inputStream, Path appRoot) throws IOException {
try (DataInputStream in = new DataInputStream(inputStream)) {
if (in.readInt() != MAGIC) {
throw new RuntimeException("Wrong magic number");
}
if (in.readInt() != VERSION) {
throw new RuntimeException("Wrong class path version");
}
String mainClass = in.readUTF();
ResourceDirectoryTracker resourceDirectoryTracker = new ResourceDirectoryTracker();
int numPaths = in.readUnsignedShort();
ClassLoadingResource[] allClassLoadingResources = new ClassLoadingResource[numPaths];
ClassLoadingResource generatedBytecodeClassLoadingResource = null;
Set<String> generatedBytecode = Set.of();
ClassLoadingResource transformedBytecodeClassLoadingResource = null;
Set<String> transformedBytecode = Set.of();
for (int pathCount = 0; pathCount < numPaths; pathCount++) {
String path = in.readUTF();
boolean hasManifest = in.readBoolean();
ManifestInfo info = null;
if (hasManifest) {
info = new ManifestInfo(readNullableString(in), readNullableString(in), readNullableString(in),
readNullableString(in), readNullableString(in), readNullableString(in));
}
JarResource resource = new JarResource(info, appRoot.resolve(path));View on GitHub (pinned to e1c734241f)
Solutions
- Rebuild the whole application with the same Quarkus version used by the runner (mvn clean package or gradle clean build)
- Ensure the quarkus-run.jar / bootstrap runner version matches the version that produced the app artifacts — do not mix runner jars across Quarkus releases
- Delete stale target/ or build/ directories and regenerate the fast-jar output
- If reading programmatically, use a SerializedApplication reader from the same Quarkus version that built the application
Example fix
// before: mixing runner and app from different versions java -jar old-quarkus-run/quarkus-run.jar -jarg new-app/quarkus-application.dat // after: regenerate both from one build ./mvnw clean package && java -jar target/quarkus-app/quarkus-run.jar
Defensive patterns
Strategy: try-catch
Validate before calling
// Java: pre-check the serialized app version before reading fully
try (DataInputStream in = new DataInputStream(Files.newInputStream(appFile))) {
int magic = in.readInt();
int version = in.readInt();
if (magic != MAGIC || version != EXPECTED_VERSION) {
throw new IllegalStateException("App built with incompatible Quarkus version (version=" + version + "); rebuild required");
}
} Type guard
static boolean isCompatibleVersion(int version) { return version == VERSION; } Try / catch
try {
SerializedApplication app = SerializedApplication.read(in, appRoot);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("Wrong class path version")) {
throw new IllegalStateException("Runner and application Quarkus versions differ; run a clean rebuild", e);
}
throw e;
} Prevention
- Always launch the app with the quarkus-run.jar produced by the same build as the fast-jar artifacts
- Run clean builds after upgrading Quarkus; never mix target/ outputs across versions
- Pin the Quarkus BOM version so runner and application modules stay in sync
- Add a startup smoke test in CI that boots the packaged jar after each build
When it happens
Trigger: Calling SerializedApplication.read(InputStream, Path) on an io.quarkus.app-files (serialized application) file whose embedded int version does not equal the VERSION constant compiled into the reader — typically when the app-cd/binaries were built by a different Quarkus version than the one loading them.
Common situations: Mixed-version deployments: rebuilding only part of an application with a newer Quarkus, copying an old quarkus-run.jar against a new application artifact (or vice versa), or stale build output in target/ after a Quarkus upgrade.
Related errors
- Unsupported AOT cache version: expected ${VERSION} but got $
- ${misalignmentReport}
- Unable to deserialize the dev mode context. Does the Quarkus
- Failed to record call to method ${call.method}
- Failed to substitute ${param}
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/02aac8e107d79537.
Report an issue: GitHub.