{"record":{"id":"29438537ad6ac554","repo":"apache/maven","slug":"artifact-already-attached-replacing-previous","errorCode":null,"errorMessage":"artifact '{}' already attached, replacing previous instance","messagePattern":"artifact '(.+?)' already attached, replacing previous instance","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java","lineNumber":1095,"sourceCode":"        return this.injectedProfileIds;\n    }\n\n    /**\n     * Add or replace an artifact. This method is now deprecated. Use the @{MavenProjectHelper} to attach artifacts to a\n     * project. In spite of the 'throws' declaration on this API, this method has never thrown an exception since Maven\n     * 3.0.x. Historically, it logged and ignored a second addition of the same g/a/v/c/t. Now it replaces the file for\n     * the artifact, so that plugins (e.g. shade) can change the pathname of the file for a particular set of\n     * coordinates.\n     *\n     * @param artifact the artifact to add or replace.\n     * @deprecated Please use {@link MavenProjectHelper}\n     * @throws DuplicateArtifactAttachmentException will never happen but leave it for backward compatibility\n     */\n    public void addAttachedArtifact(Artifact artifact) throws DuplicateArtifactAttachmentException {\n        // if already there we remove it and add again\n        int index = attachedArtifacts.indexOf(artifact);\n        if (index >= 0) {\n            LOGGER.warn(\"artifact '{}' already attached, replacing previous instance\", artifact);\n            attachedArtifacts.set(index, artifact);\n        } else {\n            attachedArtifacts.add(artifact);\n        }\n    }\n\n    /**\n     * Returns a read-only list of the attached artifacts to this project.\n     *\n     * @return the attached artifacts of this project\n     */\n    public List<Artifact> getAttachedArtifacts() {\n        if (attachedArtifacts == null) {\n            attachedArtifacts = new ArrayList<>();\n        }\n        return Collections.unmodifiableList(attachedArtifacts);\n    }\n","sourceCodeStart":1077,"sourceCodeEnd":1113,"githubUrl":"https://github.com/apache/maven/blob/e4093d4e120eac99d6bdce5ba67cace2f3085c97/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java#L1077-L1113","documentation":"MavenProject.addAttachedArtifact() was called with coordinates (groupId:artifactId:version:classifier:type) that already exist in the attached-artifacts list. Since 3.0.x the method replaces the previous instance instead of throwing DuplicateArtifactAttachmentException (kept only for binary compatibility); the old file reference is discarded. The method is deprecated in favor of MavenProjectHelper. The warning fires on every replacement, which is how plugins like shade intentionally retarget an attached artifact's file path.","triggerScenarios":"A mojo calls project.addAttachedArtifact(artifact) or MavenProjectHelper.attachArtifact(...) twice with identical g/a/v/c/t but different files: two plugin executions in the same lifecycle run both attaching (e.g. shade + source plugin attaching the same classifier), or a plugin re-running on a cached MavenProject instance.","commonSituations":"shade plugin replacing the main artifact's file after another plugin already attached it; source/javadoc plugins executing twice due to duplicated execution bindings; custom mojos attaching test-jar and a classified jar with an empty classifier by mistake; incremental builds reusing a project instance.","solutions":["Inspect the effective lifecycle (mvn -X or mvn help:effective-pom) for two executions binding plugins that attach artifacts with the same classifier","Give each attachment a distinct <classifier> so both files are kept","If the replacement is intended (shade retargeting), treat the warning as expected noise or raise the logger threshold for org.apache.maven.project.MavenProject","In custom mojos, switch to MavenProjectHelper.attachArtifact(...) and guard with a getAttachedArtifacts() lookup before attaching"],"exampleFix":"<!-- before: two executions attach artifacts with no classifier, second replaces first -->\n<plugin>\n  <artifactId>maven-shade-plugin</artifactId>\n  <executions>\n    <execution>\n      <phase>package</phase>\n      <goals><goal>shade</goal></goals>\n    </execution>\n  </executions>\n</plugin>\n\n<!-- after: shaded jar gets its own classifier, both artifacts installed -->\n<plugin>\n  <artifactId>maven-shade-plugin</artifactId>\n  <executions>\n    <execution>\n      <phase>package</phase>\n      <goals><goal>shade</goal></goals>\n      <configuration>\n        <shadedArtifactAttached>true</shadedArtifactAttached>\n        <shadedClassifierName>shaded</shadedClassifierName>\n      </configuration>\n    </execution>\n  </executions>\n</plugin>","handlingStrategy":"validation","validationCode":"// In a mojo: only attach when the coordinates are not already present\nimport org.apache.maven.artifact.Artifact;\n\nboolean alreadyAttached(MavenProject project, Artifact artifact) {\n    return project.getAttachedArtifacts().stream().anyMatch(a ->\n            a.getArtifactId().equals(artifact.getArtifactId())\n            && a.getGroupId().equals(artifact.getGroupId())\n            && a.getVersion().equals(artifact.getVersion())\n            && java.util.Objects.equals(a.getClassifier(), artifact.getClassifier())\n            && a.getType().equals(artifact.getType()));\n}\nif (!alreadyAttached(project, artifact)) {\n    project.addAttachedArtifact(artifact); // prefer MavenProjectHelper in production code\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer MavenProjectHelper.attachArtifact(...) over the deprecated MavenProject.addAttachedArtifact","Give every attached artifact a unique classifier per producing execution","Review effective lifecycle bindings so two executions never attach the same g/a/v/c/t","Remember DuplicateArtifactAttachmentException is never thrown anymore; do not rely on it for control flow"],"tags":["maven","attached-artifact","classifier","mojo-development"],"backgroundTag":"duplicate-artifact-attachment","analyzedSha":"e4093d4e120eac99d6bdce5ba67cace2f3085c97","analyzedAt":"2026-08-21T22:58:24.034Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}