{"record":{"id":"4bcddbec4a85d93c","repo":"quarkusio/quarkus","slug":"too-many-default-routes","errorCode":null,"errorMessage":"Too many default routes.","messagePattern":"Too many default routes\\.","errorType":"exception","errorClass":"BuildException","httpStatus":null,"severity":"error","filePath":"extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/VertxHttpProcessor.java","lineNumber":468,"sourceCode":"            VertxHttpBuildTimeConfig httpBuildTimeConfig,\n            List<RequireBodyHandlerBuildItem> requireBodyHandlerBuildItems,\n            BodyHandlerBuildItem bodyHandlerBuildItem,\n            List<ErrorPageActionsBuildItem> errorPageActionsBuildItems,\n            BuildProducer<ShutdownListenerBuildItem> shutdownListenerBuildItemBuildProducer,\n            LiveReloadConfig lrc,\n            CoreVertxBuildItem core, // Injected to be sure that Vert.x has been produced before calling this method.\n            ExecutorBuildItem executorBuildItem,\n            TlsRegistryBuildItem tlsRegistryBuildItem, // Injected to be sure that the TLS registry has been produced before calling this method.\n            Optional<VertxDevUILogBuildItem> vertxDevUILogBuildItem)\n            throws BuildException {\n\n        Optional<DefaultRouteBuildItem> defaultRoute;\n        if (defaultRoutes == null || defaultRoutes.isEmpty()) {\n            defaultRoute = Optional.empty();\n        } else {\n            if (defaultRoutes.size() > 1) {\n                // this should never happen\n                throw new BuildException(\"Too many default routes.\", Collections.emptyList());\n            } else {\n                defaultRoute = Optional.of(defaultRoutes.get(0));\n            }\n        }\n\n        GracefulShutdownFilter gracefulShutdownFilter = recorder.createGracefulShutdownHandler();\n        shutdownListenerBuildItemBuildProducer.produce(new ShutdownListenerBuildItem(gracefulShutdownFilter));\n\n        List<Filter> listOfFilters = filters.stream()\n                .filter(f -> f.getHandler() != null)\n                .map(FilterBuildItem::toFilter).collect(Collectors.toList());\n\n        List<Filter> listOfManagementInterfaceFilters = managementInterfacefilters.stream()\n                .filter(f -> f.getHandler() != null)\n                .map(ManagementInterfaceFilterBuildItem::toFilter).collect(Collectors.toList());\n\n        Optional<RuntimeValue<Router>> mainRouter = httpRouteRouter.getMainRouter() != null\n                ? Optional.of(httpRouteRouter.getMainRouter())","sourceCodeStart":450,"sourceCodeEnd":486,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/VertxHttpProcessor.java#L450-L486","documentation":"finalizeRouter expects at most one DefaultRouteBuildItem; if more than one producer supplied a default route the aggregation fails with BuildException. The comment notes 'this should never happen' — it is an invariant check that multiple extensions/processors tried to define the default route. Only the first would be honored otherwise, silently masking a conflict.","triggerScenarios":"Two or more @BuildStep methods producing DefaultRouteBuildItem in the same application, e.g. an extension and application code both producing a default route, leading defaultRoutes.size() > 1 in finalizeRouter.","commonSituations":"Adding a custom DefaultRouteBuildItem producer while another extension (or quarkus-vertx-http itself) already defines one; duplicated build-step logic after merging extensions.","solutions":["Remove your custom DefaultRouteBuildItem producer or the conflicting extension's one — exactly one may exist","Use an @Recorder/@BuildStep combination guarded by a capability or config condition so only one default route is produced in a given app","Search the build for 'DefaultRouteBuildItem' producers to identify the two conflicting sources"],"exampleFix":"// before (app producer conflicting with framework)\n@BuildStep DefaultRouteBuildItem mine() { return new DefaultRouteBuildItem(\"/app\"); }\n// after — delete the producer, or gate it:\n@BuildStep(onlyIfNot = DefaultRouteProvided.class) DefaultRouteBuildItem mine() { ... }","handlingStrategy":"validation","validationCode":"long producers = buildSteps.stream()\n    .filter(s -> s.produces(DefaultRouteBuildItem.class).count() > 0)\n    .count();\nif (producers > 1) {\n    throw new IllegalStateException(\"multiple DefaultRouteBuildItem producers\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    finalizeRouter(...);\n} catch (BuildException e) {\n    if (e.getMessage().contains(\"Too many default routes\")) {\n        // locate duplicate DefaultRouteBuildItem producers and remove one\n    }\n    throw e;\n}","preventionTips":["Produce DefaultRouteBuildItem from at most one build step in an application","Gate default-route producers behind capabilities or config conditions when writing shared extensions","Grep the dependency tree/extension sources for DefaultRouteBuildItem producers before adding your own"],"tags":["quarkus","vertx-http","routing","duplicate-build-item","build-time"],"backgroundTag":"duplicate-build-item","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}