{"record":{"id":"5c46200d121e3313","repo":"apache/maven","slug":"cannot-attach-artifact-to-project-groupid-artifa","errorCode":null,"errorMessage":"Cannot attach artifact to project: groupId, artifactId and version must match the project.%n  Project coordinates:  %s:%s:%s%n  Artifact coordinates: %s:%s:%s","messagePattern":"Cannot attach artifact to project: groupId, artifactId and version must match the project\\.%n  Project coordinates:  (.+?):(.+?):(.+?)%n  Artifact coordinates: (.+?):(.+?):(.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java","lineNumber":170,"sourceCode":"                                + \"and artifactId must match either the project or a declared module name.%n\"\n                                + \"  Project coordinates:  %s:%s:%s%n\"\n                                + \"  Artifact coordinates: %s:%s:%s%n\",\n                        g1, a1, v1, g2, a2, v2);\n                if (isSameGroupAndVersion) {\n                    message += String.format(\n                            \"  Hint: The artifactId '%s' does not match the project artifactId '%s' \"\n                                    + \"nor any declared module name in source roots.\",\n                            a2, a1);\n                }\n            } else {\n                // Non-modular project: artifactId must match exactly\n                message = String.format(\n                        \"Cannot attach artifact to project: groupId, artifactId and version must match the project.%n\"\n                                + \"  Project coordinates:  %s:%s:%s%n\"\n                                + \"  Artifact coordinates: %s:%s:%s\",\n                        g1, a1, v1, g2, a2, v2);\n            }\n            throw new IllegalArgumentException(message);\n        }\n        getMavenProject(project)\n                .addAttachedArtifact(\n                        RepositoryUtils.toArtifact(getSession(project).toArtifact(artifact)));\n        artifactManager.setPath(artifact, path);\n    }\n\n    @Nonnull\n    @Override\n    public Collection<SourceRoot> getSourceRoots(@Nonnull Project project) {\n        MavenProject prj = getMavenProject(requireNonNull(project, \"project\" + \" cannot be null\"));\n        return prj.getSourceRoots();\n    }\n\n    @Nonnull\n    @Override\n    public Stream<SourceRoot> getEnabledSourceRoots(@Nonnull Project project, ProjectScope scope, Language language) {\n        MavenProject prj = getMavenProject(requireNonNull(project, \"project\" + \" cannot be null\"));","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/apache/maven/blob/e4093d4e120eac99d6bdce5ba67cace2f3085c97/impl/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java#L152-L188","documentation":"IllegalArgumentException from ProjectManager.attachArtifact(project, artifact, path): the artifact's coordinates must match the project's. groupId and base version must equal the project's; artifactId must equal the project's artifactId — or, for modular multi-module source layouts, one of the module names declared in the project's source roots (sr.module()). The non-modular message variant prints both coordinate triples for comparison.","triggerScenarios":"session.getService(ProjectManager.class).attachArtifact(...) with an artifact whose groupId or version differs from the project, or whose artifactId differs on a project with no module-declaring source roots. Empty coordinates are auto-filled from the project first, so only mismatching non-empty values reach the check.","commonSituations":"Mojos attaching secondary artifacts with hand-built coordinates instead of the project's; attaching an artifact produced for a different subproject; refactoring project coordinates without updating attachArtifact call sites; JPMS module names that differ from the project artifactId.","solutions":["Build the attached artifact from the project's own groupId/artifactId/version and vary only classifier and extension","For JPMS multi-module layouts, make the artifactId match a module name declared in a source root","Validate coordinates against project.getGroupId()/getArtifactId()/getVersion() before attaching"],"exampleFix":"// before: coordinates differ from the project\nArtifact a = session.createArtifact(\"other.group\", \"other-artifact\", \"1.0\", \"jar\");\nprojectManager.attachArtifact(project, session.createProducedArtifact(\n    \"other.group\", \"other-artifact\", \"1.0\", null, \"jar\", null), path);\n\n// after: project coordinates, only classifier differs\nProducedArtifact a = session.createProducedArtifact(\n    project.getGroupId(), project.getArtifactId(), project.getVersion(),\n    \"sources\", \"jar\", null);\nprojectManager.attachArtifact(project, a, path);","handlingStrategy":"validation","validationCode":"// Verify coordinates before attaching\nboolean artifactIdOk = artifact.getArtifactId().equals(project.getArtifactId())\n    || project.getSourceRoots().stream().map(SourceRoot::module)\n        .flatMap(Optional::stream).anyMatch(artifact.getArtifactId()::equals);\nif (!(artifact.getGroupId().equals(project.getGroupId())\n        && artifact.getBaseVersion().toString().equals(project.getVersion())\n        && artifactIdOk)) {\n    throw new IllegalArgumentException(\n        \"Refusing to attach artifact with foreign coordinates: \" + artifact);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive attached-artifact coordinates from the project; vary only classifier/extension","Keep module names in source roots consistent with artifactIds for JPMS layouts","Add unit tests asserting attachArtifact succeeds for every artifact a mojo produces"],"tags":["maven","attached-artifact","coordinates","project-manager","maven-api"],"backgroundTag":"artifact-coordinate-mismatch","analyzedSha":"e4093d4e120eac99d6bdce5ba67cace2f3085c97","analyzedAt":"2026-08-21T22:58:24.034Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}