quarkusio/quarkus · error · IllegalStateException

Duplicate key %s (attempted merging values %s and %s)

Error message

Duplicate key %s (attempted merging values %s and %s)

What it means

When wiring additional named handlers (e.g. from other extensions via AdditionalLoggingSetup / named handler maps), the collector uses putIfAbsent and throws IllegalStateException "Duplicate key %s (attempted merging values ...)" if two handlers share the same name. This prevents silently overwriting a handler registered by another part of the application.

Source

Thrown at core/runtime/src/main/java/io/quarkus/runtime/logging/LoggingSetupRecorder.java:953

        private final Map<String, Handler> additionalNamedHandlersMap;
        private final ErrorManager errorManager;
        private final Collection<LogCleanupFilterElement> filterElements;

        private final ShutdownNotifier shutdownNotifier;

        public AdditionalNamedHandlersConsumer(Map<String, Handler> additionalNamedHandlersMap, ErrorManager errorManager,
                Collection<LogCleanupFilterElement> filterElements, ShutdownNotifier shutdownNotifier) {
            this.additionalNamedHandlersMap = additionalNamedHandlersMap;
            this.errorManager = errorManager;
            this.filterElements = filterElements;
            this.shutdownNotifier = shutdownNotifier;
        }

        @Override
        public void accept(String name, Handler handler) {
            Handler previous = additionalNamedHandlersMap.putIfAbsent(name, handler);
            if (previous != null) {
                throw new IllegalStateException(String.format(
                        "Duplicate key %s (attempted merging values %s and %s)",
                        name, previous, handler));
            }
            handler.setErrorManager(errorManager);
            handler.setFilter(new LogCleanupFilter(filterElements, shutdownNotifier));
        }
    }

    public static class ShutdownNotifier implements ShutdownListener {
        volatile boolean shutdown;

        @Override
        public void shutdown(ShutdownNotification notification) {
            shutdown = true;
            notification.done();
        }
    }
}

View on GitHub (pinned to e1c734241f)

Solutions

  1. Rename one of the handlers so names are unique across all registration sources
  2. Find which extensions/build items register the conflicting handler and remove or rename the duplicate
  3. If you own the code, use distinct handler names per functional area

Example fix

// before: two recorders both do namedHandlers.put("MAIN", handler)
// after
namedHandler("APP_MAIN", appHandler);
namedHandler("EXT_MAIN", extHandler);
Defensive patterns

Strategy: try-catch

Validate before calling

// detect duplicates before registering additional named handlers
if (additionalNamedHandlersMap.containsKey(name)) throw new IllegalStateException("Handler already registered: " + name);

Try / catch

try { registerAdditionalHandlers(map); } catch (IllegalStateException e) { if (e.getMessage().startsWith("Duplicate key")) log.error("Rename one of the conflicting named handlers"); else throw e; }

Prevention

When it happens

Trigger: Two sources (e.g. an extension recorder and application configuration) register additional named log handlers with the same name into the additional named handlers map during logging setup.

Common situations: Multiple extensions each registering a named handler with a generic name like "MAIN"; duplicate AdditionalLoggingSetup build items; a custom handler registered both via config and via a recorder.

Related errors


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