{"record":{"id":"02aac8e107d79537","repo":"quarkusio/quarkus","slug":"wrong-class-path-version","errorCode":null,"errorMessage":"Wrong class path version","messagePattern":"Wrong class path version","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/SerializedApplication.java","lineNumber":138,"sourceCode":"            data.writeShort(fullyIndexedResourcesToCPJarIndex.size());\n            for (Map.Entry<String, List<Integer>> entry : fullyIndexedResourcesToCPJarIndex.entrySet()) {\n                data.writeUTF(entry.getKey());\n                data.writeShort(entry.getValue().size());\n                for (Integer index : entry.getValue()) {\n                    data.writeShort(index);\n                }\n            }\n            data.flush();\n        }\n    }\n\n    public static SerializedApplication read(InputStream inputStream, Path appRoot) throws IOException {\n        try (DataInputStream in = new DataInputStream(inputStream)) {\n            if (in.readInt() != MAGIC) {\n                throw new RuntimeException(\"Wrong magic number\");\n            }\n            if (in.readInt() != VERSION) {\n                throw new RuntimeException(\"Wrong class path version\");\n            }\n            String mainClass = in.readUTF();\n            ResourceDirectoryTracker resourceDirectoryTracker = new ResourceDirectoryTracker();\n            int numPaths = in.readUnsignedShort();\n            ClassLoadingResource[] allClassLoadingResources = new ClassLoadingResource[numPaths];\n            ClassLoadingResource generatedBytecodeClassLoadingResource = null;\n            Set<String> generatedBytecode = Set.of();\n            ClassLoadingResource transformedBytecodeClassLoadingResource = null;\n            Set<String> transformedBytecode = Set.of();\n            for (int pathCount = 0; pathCount < numPaths; pathCount++) {\n                String path = in.readUTF();\n                boolean hasManifest = in.readBoolean();\n                ManifestInfo info = null;\n                if (hasManifest) {\n                    info = new ManifestInfo(readNullableString(in), readNullableString(in), readNullableString(in),\n                            readNullableString(in), readNullableString(in), readNullableString(in));\n                }\n                JarResource resource = new JarResource(info, appRoot.resolve(path));","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/bootstrap/runner/src/main/java/io/quarkus/bootstrap/runner/SerializedApplication.java#L120-L156","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: mixing runner and app from different versions\njava -jar old-quarkus-run/quarkus-run.jar -jarg new-app/quarkus-application.dat\n// after: regenerate both from one build\n./mvnw clean package && java -jar target/quarkus-app/quarkus-run.jar","handlingStrategy":"try-catch","validationCode":"// Java: pre-check the serialized app version before reading fully\ntry (DataInputStream in = new DataInputStream(Files.newInputStream(appFile))) {\n    int magic = in.readInt();\n    int version = in.readInt();\n    if (magic != MAGIC || version != EXPECTED_VERSION) {\n        throw new IllegalStateException(\"App built with incompatible Quarkus version (version=\" + version + \"); rebuild required\");\n    }\n}","typeGuard":"static boolean isCompatibleVersion(int version) { return version == VERSION; }","tryCatchPattern":"try {\n    SerializedApplication app = SerializedApplication.read(in, appRoot);\n} catch (RuntimeException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"Wrong class path version\")) {\n        throw new IllegalStateException(\"Runner and application Quarkus versions differ; run a clean rebuild\", e);\n    }\n    throw e;\n}","preventionTips":["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"],"tags":["serialization","version-mismatch","quarkus-runner"],"backgroundTag":"serialization-version-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}