{"record":{"id":"bc96d73b596dd7d2","repo":"quarkusio/quarkus","slug":"failed-to-deserialize-extension-metadata-from-ur","errorCode":null,"errorMessage":"Failed to deserialize extension metadata from ${url}","messagePattern":"Failed to deserialize extension metadata from (.+?)","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/state/TopExtensionDependency.java","lineNumber":55,"sourceCode":"\n        public Builder setCatalogMetadata(Extension metadata) {\n            this.catalogMetadata = metadata;\n            return this;\n        }\n\n        public Builder setTransitive(boolean transitive) {\n            this.transitive = transitive;\n            return this;\n        }\n\n        public TopExtensionDependency build() {\n            if (catalogMetadata == null) {\n                catalogMetadata = ExtensionMetadataUtil.applyExtensionMetadata(\n                        resolvedDep.getContentTree(), visit -> {\n                            try {\n                                return Extension.fromFile(visit.getPath());\n                            } catch (IOException e) {\n                                throw new UncheckedIOException(\n                                        \"Failed to deserialize extension metadata from \" + visit.getUrl(), e);\n                            }\n                        });\n            }\n            return new TopExtensionDependency(coords, catalogMetadata, ExtensionProvider.key(getOrigin(catalogMetadata)),\n                    transitive);\n        }\n\n        public ArtifactKey getKey() {\n            return resolvedDep == null ? null : resolvedDep.getKey();\n        }\n\n        private static ExtensionOrigin getOrigin(Extension metadata) {\n            if (metadata == null || metadata.getOrigins().isEmpty()) {\n                return null;\n            }\n            ExtensionOrigin origin = metadata.getOrigins().get(0);\n            if (origin.isPlatform()) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/state/TopExtensionDependency.java#L37-L73","documentation":"When building a TopExtensionDependency without pre-supplied catalog metadata, the devtools read the extension's quarkus-extension.json descriptor from the resolved artifact's content tree and deserialize it into an Extension. This UncheckedIOException is thrown when reading or parsing that descriptor file fails via Extension.fromFile(), with the offending descriptor URL in the message.","triggerScenarios":"Calling TopExtensionDependency.Builder.build() when resolvedDep has no catalogMetadata and the quarkus-extension.json inside the artifact's content tree is missing, truncated, corrupted (e.g. partial download of a jar into the local Maven repository), or unreadable.","commonSituations":"Interrupted Maven downloads leaving corrupt jars in ~/.m2/repository, custom/snapshot artifacts built without the quarkus-extension descriptor, wrong classifier/type on a dependency so the wrong content tree is read, file permission problems in the local repo.","solutions":["Delete the corrupted artifact directory from the local Maven repository (~/.m2/repository/<group>/<artifact>/<version>) and re-resolve/rebuild","Check the URL in the message; open the quarkus-extension.json it points to and verify it is valid JSON","Verify the dependency is a real Quarkus extension jar containing META-INF/quarkus-extension/quarkus-extension.json","Provide catalogMetadata explicitly via Builder.setCatalogMetadata() so the file-descriptor path is skipped"],"exampleFix":"# before (corrupt cached artifact)\nmvn quarkus:update\n# after: purge the corrupt artifact then retry\nrm -rf ~/.m2/repository/io/quarkus/ext/acme/1.0.0\nmvn -U quarkus:update","handlingStrategy":"try-catch","validationCode":"// before building the dependency\ntry (var is = Files.newInputStream(visit.getPath())) {\n    new String(is.readAllBytes(), StandardCharsets.UTF_8).contains(\"\\\"dependencies\\\"\"); // sanity: JSON present\n}","typeGuard":null,"tryCatchPattern":"try {\n    TopExtensionDependency dep = TopExtensionDependency.builder()\n        .setResolvedDependency(resolvedDep).build();\n} catch (UncheckedIOException e) {\n    log.error(\"Corrupt extension descriptor at \" + e.getMessage() + \": \" + e.getCause());\n    // purge the artifact from local repo and re-resolve\n}","preventionTips":["Run with -U / refresh local repo after interrupted builds","Never kill Maven mid-download; suspect ~/.m2 if builds were cancelled","Confirm extension jars contain META-INF/quarkus-extension/quarkus-extension.json","Supply catalogMetadata explicitly when you already have registry data to avoid reading file descriptors"],"tags":["io","deserialization","extension-metadata","maven-repository"],"backgroundTag":"corrupt-artifact-descriptor","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"}