{"record":{"id":"f743f9438a281e44","repo":"quarkusio/quarkus","slug":"duplicate-endpoints-detected-the-endpoint-for-sta","errorCode":null,"errorMessage":"Duplicate endpoints detected, the endpoint for static resources must be unique: <duplicates>","messagePattern":"Duplicate endpoints detected, the endpoint for static resources must be unique: <duplicates>","errorType":"validation","errorClass":"BuildException","httpStatus":null,"severity":"error","filePath":"extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/GeneratedStaticResourcesProcessor.java","lineNumber":98,"sourceCode":"                    nativeImageResourcesProducer.produce(new NativeImageResourceBuildItem(parent));\n                }\n            }\n        }\n    }\n\n    @BuildStep(onlyIfNot = IsProduction.class)\n    @Record(ExecutionTime.RUNTIME_INIT)\n    public void process(List<GeneratedStaticResourceBuildItem> generatedStaticResources,\n            LaunchModeBuildItem launchModeBuildItem,\n            BuildProducer<RouteBuildItem> routes, GeneratedStaticResourcesRecorder generatedStaticResourcesRecorder,\n            BuildProducer<NotFoundPageDisplayableEndpointBuildItem> notFoundPageProducer) throws BuildException {\n        if (generatedStaticResources.isEmpty()) {\n            return;\n        }\n\n        List<String> duplicates = collectDuplicates(generatedStaticResources);\n        if (!duplicates.isEmpty()) {\n            throw new BuildException(\n                    \"Duplicate endpoints detected, the endpoint for static resources must be unique: \" + duplicates);\n        }\n\n        Map<String, String> generatedFilesResources = generatedStaticResources.stream()\n                .peek(path -> notFoundPageProducer.produce(new NotFoundPageDisplayableEndpointBuildItem(path.getEndpoint())))\n                .filter(GeneratedStaticResourceBuildItem::isFile)\n                .collect(Collectors.toMap(GeneratedStaticResourceBuildItem::getEndpoint,\n                        GeneratedStaticResourceBuildItem::getFileAbsolutePath));\n        Set<String> generatedClassPathResources = generatedStaticResources.stream()\n                .map(GeneratedStaticResourceBuildItem::getEndpoint)\n                .collect(Collectors.toSet());\n        routes.produce(RouteBuildItem.builder()\n                .orderedRoute(\"/*\", ROUTE_ORDER, generatedStaticResourcesRecorder.createRouteCustomizer())\n                .handler(generatedStaticResourcesRecorder.createHandler(generatedClassPathResources, generatedFilesResources))\n                .build());\n    }\n\n    private static String buildGeneratedStaticResourceLocation(","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/GeneratedStaticResourcesProcessor.java#L80-L116","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change the endpoint path of the conflicting GeneratedStaticResourceBuildItem (usually via the extension's config property)","Disable/remove one of the extensions or build steps producing the duplicate","Check the duplicate list in the error message to see which endpoints collide"],"exampleFix":"// before (two build steps)\nproduce(new GeneratedStaticResourceBuildItem(\"/assets\", ...)); // extension A\nproduce(new GeneratedStaticResourceBuildItem(\"/assets\", ...)); // extension B\n\n// after\nproduce(new GeneratedStaticResourceBuildItem(\"/assets-a\", ...));\nproduce(new GeneratedStaticResourceBuildItem(\"/assets-b\", ...));","handlingStrategy":"validation","validationCode":"Map<String, Long> counts = buildItems.stream()\n    .collect(Collectors.groupingBy(GeneratedStaticResourceBuildItem::getEndpoint, Collectors.counting()));\nList<String> dupes = counts.entrySet().stream().filter(e -> e.getValue() > 1).map(Map.Entry::getKey).toList();\nif (!dupes.isEmpty()) throw new IllegalStateException(\"Duplicate static resource endpoints: \" + dupes);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Namespace generated resource endpoints per extension or per feature","Make endpoints configurable and default to unique paths","Audit installed extensions for overlapping default static resource paths"],"tags":["build-time","static-resources","duplicate","routes"],"backgroundTag":"duplicate-route-endpoint","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"}