{"record":{"id":"b082c84fcbbbf694","repo":"quarkusio/quarkus","slug":"cannot-merge-dependencies-with-different-module-na","errorCode":null,"errorMessage":"Cannot merge dependencies with different module names","messagePattern":"Cannot merge dependencies with different module names","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"extensions/packaging/modular/spi/src/main/java/io/quarkus/modular/spi/model/DependencyInfo.java","lineNumber":24,"sourceCode":"\nimport io.smallrye.common.constraint.Assert;\nimport io.smallrye.modules.desc.Dependency;\nimport io.smallrye.modules.desc.PackageAccess;\n\npublic record DependencyInfo(\n        String moduleName,\n        Dependency.Modifier.Set modifiers,\n        Map<String, PackageAccess> packageAccesses) {\n    public DependencyInfo {\n        Assert.checkNotNullParam(\"moduleName\", moduleName);\n        Assert.checkNotNullParam(\"modifiers\", modifiers);\n        packageAccesses = Map.copyOf(Assert.checkNotNullParam(\"packageAccesses\", packageAccesses));\n    }\n\n    public static DependencyInfo merge(DependencyInfo a, DependencyInfo b) {\n        String moduleName = a.moduleName;\n        if (!moduleName.equals(b.moduleName)) {\n            throw new IllegalArgumentException(\"Cannot merge dependencies with different module names\");\n        }\n        // merge modifiers but non-synthetic takes priority over synthetic\n        Dependency.Modifier.Set modifiers = a.modifiers.xor(Dependency.Modifier.SYNTHETIC)\n                .withAll(b.modifiers.xor(Dependency.Modifier.SYNTHETIC))\n                .xor(Dependency.Modifier.SYNTHETIC);\n        Map<String, PackageAccess> packageAccesses = Stream.concat(\n                a.packageAccesses.entrySet().stream(),\n                b.packageAccesses.entrySet().stream())\n                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, PackageAccess::max));\n        return new DependencyInfo(moduleName, modifiers, packageAccesses);\n    }\n}\n","sourceCodeStart":6,"sourceCodeEnd":37,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/packaging/modular/spi/src/main/java/io/quarkus/modular/spi/model/DependencyInfo.java#L6-L37","documentation":"DependencyInfo.merge combines two DependencyInfo records that represent the same module dependency observed from different sources. It refuses to merge when the two have different module names, because the result would be ill-defined. Callers are expected to group dependencies by module name before merging.","triggerScenarios":"Calling DependencyInfo.merge(a, b) where a.moduleName != b.moduleName — e.g. merging synthetic and non-synthetic entries for different modules, or a bug in aggregation code that pairs up wrong entries.","commonSituations":"Downstream tooling (custom build steps over the modular SPI) merging a dependency list without keying by module name; refactors that change module naming between build steps.","solutions":["Group DependencyInfo instances by moduleName before merging (Map<String, List<DependencyInfo>> keyed by getModuleName)","Fix the aggregation code so a/b are guaranteed to refer to the same module","If the modules genuinely differ, keep them separate instead of merging"],"exampleFix":"// before: blind pairwise merge\nDependencyInfo m = DependencyInfo.merge(a, b);\n// after: guard by module name\nDependencyInfo m = a.getModuleName().equals(b.getModuleName())\n        ? DependencyInfo.merge(a, b) : a;","handlingStrategy":"validation","validationCode":"if (a.getModuleName() == null || !a.getModuleName().equals(b.getModuleName())) {\n    throw new IllegalArgumentException(\"Refusing to merge dependencies with different module names\");\n}\nDependencyInfo merged = DependencyInfo.merge(a, b);","typeGuard":"boolean isMergeable(DependencyInfo a, DependencyInfo b) {\n    return a != null && b != null\n            && java.util.Objects.equals(a.getModuleName(), b.getModuleName());\n}","tryCatchPattern":"try {\n    return DependencyInfo.merge(a, b);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"different module names\")) {\n        throw new IllegalStateException(\"Merge called across modules: \"\n                + a.getModuleName() + \" vs \" + b.getModuleName(), e);\n    }\n    throw e;\n}","preventionTips":["Group dependencies by moduleName before merging","Write a unit test that merges representative synthetic/non-synthetic pairs","Assert moduleName equality at aggregation boundaries"],"tags":["jpms","spi","merge"],"backgroundTag":"merge-key-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}