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
- Rename one of the handlers so names are unique across all registration sources
- Find which extensions/build items register the conflicting handler and remove or rename the duplicate
- 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
- Namespace handler names per extension (e.g. "myext-main")
- Avoid generic names like MAIN or DEFAULT for named handlers
- Audit extensions that contribute AdditionalLoggingSetup handlers
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
- Only one handler can be configured with the same name '%s'
- %s is marked @Record but does not inject an @Recorder object
- Unknown recorder constructor parameter: %s in recorder %s
- messageStarts cannot be empty
- Unimplemented mode of use of 'io.quarkus.runtime.logging.Log
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/8c9d18b14b2f461a.
Report an issue: GitHub.