quarkusio/quarkus · error · BuildException

Duplicate endpoints detected, the endpoint for static…

Error message

Duplicate endpoints detected, the endpoint for static resources must be unique: <duplicates>

What it means

GeneratedStaticResourcesProcessor validates at build time that every GeneratedStaticResourceBuildItem has a unique endpoint URL. If two or more build items produce the same endpoint, it throws BuildException listing the duplicates, because Vert.x routes would otherwise be ambiguous.

Solutions

  1. Change the endpoint path of the conflicting GeneratedStaticResourceBuildItem (usually via the extension's config property)
  2. Disable/remove one of the extensions or build steps producing the duplicate
  3. Check the duplicate list in the error message to see which endpoints collide

Example fix

// before (two build steps)
produce(new GeneratedStaticResourceBuildItem("/assets", ...)); // extension A
produce(new GeneratedStaticResourceBuildItem("/assets", ...)); // extension B

// after
produce(new GeneratedStaticResourceBuildItem("/assets-a", ...));
produce(new GeneratedStaticResourceBuildItem("/assets-b", ...));
Defensive patterns

Strategy: validation

Validate before calling

Map<String, Long> counts = buildItems.stream()
    .collect(Collectors.groupingBy(GeneratedStaticResourceBuildItem::getEndpoint, Collectors.counting()));
List<String> dupes = counts.entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).toList();
if (!dupes.isEmpty()) throw new IllegalStateException("Duplicate static resource endpoints: " + dupes);

Prevention

When it happens

Trigger: Two extensions or two build steps each produce a GeneratedStaticResourceBuildItem with the same endpoint path; GeneratedStaticResourceProcessor.process detects duplicates via collectDuplicates and fails the build.

Common situations: Installing multiple Quarkus extensions that both generate static resources under the same default endpoint (e.g. two UI extensions choosing the same path); an application's own build step colliding with an extension's default path; upgrading an extension that changed its default endpoint into an existing one.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/f743f9438a281e44. Report an issue: GitHub.

Appendix: source

Thrown at extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/GeneratedStaticResourcesProcessor.java:98

                    nativeImageResourcesProducer.produce(new NativeImageResourceBuildItem(parent));
                }
            }
        }
    }

    @BuildStep(onlyIfNot = IsProduction.class)
    @Record(ExecutionTime.RUNTIME_INIT)
    public void process(List<GeneratedStaticResourceBuildItem> generatedStaticResources,
            LaunchModeBuildItem launchModeBuildItem,
            BuildProducer<RouteBuildItem> routes, GeneratedStaticResourcesRecorder generatedStaticResourcesRecorder,
            BuildProducer<NotFoundPageDisplayableEndpointBuildItem> notFoundPageProducer) throws BuildException {
        if (generatedStaticResources.isEmpty()) {
            return;
        }

        List<String> duplicates = collectDuplicates(generatedStaticResources);
        if (!duplicates.isEmpty()) {
            throw new BuildException(
                    "Duplicate endpoints detected, the endpoint for static resources must be unique: " + duplicates);
        }

        Map<String, String> generatedFilesResources = generatedStaticResources.stream()
                .peek(path -> notFoundPageProducer.produce(new NotFoundPageDisplayableEndpointBuildItem(path.getEndpoint())))
                .filter(GeneratedStaticResourceBuildItem::isFile)
                .collect(Collectors.toMap(GeneratedStaticResourceBuildItem::getEndpoint,
                        GeneratedStaticResourceBuildItem::getFileAbsolutePath));
        Set<String> generatedClassPathResources = generatedStaticResources.stream()
                .map(GeneratedStaticResourceBuildItem::getEndpoint)
                .collect(Collectors.toSet());
        routes.produce(RouteBuildItem.builder()
                .orderedRoute("/*", ROUTE_ORDER, generatedStaticResourcesRecorder.createRouteCustomizer())
                .handler(generatedStaticResourcesRecorder.createHandler(generatedClassPathResources, generatedFilesResources))
                .build());
    }

    private static String buildGeneratedStaticResourceLocation(

View on GitHub (pinned to e1c734241f)