You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2026/06/01 19:54:41 UTC
(maven) 04/05: Improve error message for prefix-based remote repository filtering (PR #11888)
This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch maven-4.0.x-test-fixes
in repository https://gitbox.apache.org/repos/asf/maven.git
commit ded2a5a7c86cfdec3660fb82a1a19bca9d5338d1
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Mon Jun 1 21:53:52 2026 +0200
Improve error message for prefix-based remote repository filtering (PR #11888)
Cherry-pick from ci-issue-11856 branch.
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---
.../maven/exception/DefaultExceptionHandler.java | 34 +++++++++++++++++-
.../exception/DefaultExceptionHandlerTest.java | 40 ++++++++++++++++++++++
2 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/impl/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java b/impl/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java
index 98db980812..fdf2441bec 100644
--- a/impl/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java
+++ b/impl/maven-core/src/main/java/org/apache/maven/exception/DefaultExceptionHandler.java
@@ -40,6 +40,7 @@
import org.apache.maven.plugin.PluginExecutionException;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingResult;
+import org.eclipse.aether.transfer.ArtifactFilteredOutException;
/*
@@ -177,6 +178,9 @@ private String getReference(Set<Throwable> dejaVu, Throwable exception) {
reference = ConnectException.class.getSimpleName();
}
}
+ if (findCause(exception, ArtifactFilteredOutException.class) != null) {
+ reference = "https://maven.apache.org/resolver/remote-repository-filtering.html";
+ }
} else if (exception instanceof LinkageError) {
reference = LinkageError.class.getSimpleName();
} else if (exception instanceof PluginExecutionException) {
@@ -207,7 +211,9 @@ private String getReference(Set<Throwable> dejaVu, Throwable exception) {
}
}
- if ((reference != null && !reference.isEmpty()) && !reference.startsWith("http:")) {
+ if ((reference != null && !reference.isEmpty())
+ && !reference.startsWith("http:")
+ && !reference.startsWith("https:")) {
reference = "http://cwiki.apache.org/confluence/display/MAVEN/" + reference;
}
@@ -229,6 +235,8 @@ private boolean isNoteworthyException(Throwable exception) {
private String getMessage(String message, Throwable exception) {
String fullMessage = (message != null) ? message : "";
+ boolean hasArtifactFilteredOut = false;
+
// To break out of possible endless loop when getCause returns "this", or dejaVu for n-level recursion (n>1)
Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
for (Throwable t = exception; t != null && t != t.getCause(); t = t.getCause()) {
@@ -260,15 +268,39 @@ private String getMessage(String message, Throwable exception) {
fullMessage = join(fullMessage, exceptionMessage);
}
+ if (t instanceof ArtifactFilteredOutException) {
+ hasArtifactFilteredOut = true;
+ }
+
if (!dejaVu.add(t)) {
fullMessage = join(fullMessage, "[CIRCULAR REFERENCE]");
break;
}
}
+ if (hasArtifactFilteredOut) {
+ fullMessage += """
+
+ This error indicates that a remote repository filter has rejected this artifact. This commonly happens with repository managers using virtual/group repositories that do not properly aggregate prefix files.
+ To disable remote repository filtering, add one or both of these to your command line or to .mvn/maven.config:
+ -Daether.remoteRepositoryFilter.prefixes=false
+ -Daether.remoteRepositoryFilter.groupId=false
+ See https://maven.apache.org/resolver/remote-repository-filtering.html""";
+ }
+
return fullMessage.trim();
}
+ private static <T extends Throwable> T findCause(Throwable exception, Class<T> type) {
+ Set<Throwable> dejaVu = Collections.newSetFromMap(new IdentityHashMap<>());
+ for (Throwable t = exception; t != null && dejaVu.add(t); t = t.getCause()) {
+ if (type.isInstance(t)) {
+ return type.cast(t);
+ }
+ }
+ return null;
+ }
+
private String join(String message1, String message2) {
String message = "";
diff --git a/impl/maven-core/src/test/java/org/apache/maven/exception/DefaultExceptionHandlerTest.java b/impl/maven-core/src/test/java/org/apache/maven/exception/DefaultExceptionHandlerTest.java
index c9a84014d2..88359e2e8f 100644
--- a/impl/maven-core/src/test/java/org/apache/maven/exception/DefaultExceptionHandlerTest.java
+++ b/impl/maven-core/src/test/java/org/apache/maven/exception/DefaultExceptionHandlerTest.java
@@ -29,9 +29,15 @@
import org.apache.maven.plugin.PluginExecutionException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.repository.RemoteRepository;
+import org.eclipse.aether.resolution.ArtifactResolutionException;
+import org.eclipse.aether.resolution.ArtifactResult;
+import org.eclipse.aether.transfer.ArtifactFilteredOutException;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
*/
@@ -124,6 +130,40 @@ public synchronized Throwable getCause() {
assertEquals(expectedReference, summary.getReference());
}
+ @Test
+ void testArtifactFilteredOutException() {
+ RemoteRepository repo =
+ new RemoteRepository.Builder("my-repo", "default", "https://repo.example.com/maven").build();
+ ArtifactFilteredOutException filterEx = new ArtifactFilteredOutException(
+ new DefaultArtifact("com.example:my-lib:jar:1.0"),
+ repo,
+ "Prefix com/example/my-lib/1.0/my-lib-1.0.jar NOT allowed from my-repo"
+ + " (https://repo.example.com/maven, default, releases)");
+ ArtifactResult artifactResult = new ArtifactResult(new org.eclipse.aether.resolution.ArtifactRequest(
+ new DefaultArtifact("com.example:my-lib:jar:1.0"), java.util.List.of(repo), null));
+ artifactResult.addException(filterEx);
+ ArtifactResolutionException resolutionEx =
+ new ArtifactResolutionException(java.util.List.of(artifactResult), "Could not resolve artifact");
+ MojoExecutionException mojoEx = new MojoExecutionException("Resolution failed", resolutionEx);
+
+ DefaultExceptionHandler handler = new DefaultExceptionHandler();
+ ExceptionSummary summary = handler.handleException(mojoEx);
+
+ assertTrue(
+ summary.getMessage().contains("-Daether.remoteRepositoryFilter.prefixes=false"),
+ "Message should contain the prefixes workaround property");
+ assertTrue(
+ summary.getMessage().contains("-Daether.remoteRepositoryFilter.groupId=false"),
+ "Message should contain the groupId workaround property");
+ assertTrue(
+ summary.getMessage().contains("remote repository filter"),
+ "Message should explain the filtering cause");
+ assertEquals(
+ "https://maven.apache.org/resolver/remote-repository-filtering.html",
+ summary.getReference(),
+ "Reference should point to the RRF documentation");
+ }
+
@Test
void testHandleExceptionSelfReferencing() {
RuntimeException boom3 = new RuntimeException("BOOM3");