{"record":{"id":"e264a56fc3d4cf96","repo":"LMAX-Exchange/disruptor","slug":"setdefaultexceptionhandler-can-not-be-used-after-h","errorCode":null,"errorMessage":"setDefaultExceptionHandler can not be used after handleExceptionsWith","messagePattern":"setDefaultExceptionHandler can not be used after handleExceptionsWith","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/lmax/disruptor/dsl/Disruptor.java","lineNumber":233,"sourceCode":"    public void handleExceptionsWith(final ExceptionHandler<? super T> exceptionHandler)\n    {\n        this.exceptionHandler = exceptionHandler;\n    }\n\n    /**\n     * <p>Specify an exception handler to be used for event handlers and worker pools created by this Disruptor.</p>\n     *\n     * <p>The exception handler will be used by existing and future event handlers and worker pools created by this Disruptor instance.</p>\n     *\n     * @param exceptionHandler the exception handler to use.\n     */\n    @SuppressWarnings(\"unchecked\")\n    public void setDefaultExceptionHandler(final ExceptionHandler<? super T> exceptionHandler)\n    {\n        checkNotStarted();\n        if (!(this.exceptionHandler instanceof ExceptionHandlerWrapper))\n        {\n            throw new IllegalStateException(\"setDefaultExceptionHandler can not be used after handleExceptionsWith\");\n        }\n        ((ExceptionHandlerWrapper<T>) this.exceptionHandler).switchTo(exceptionHandler);\n    }\n\n    /**\n     * Override the default exception handler for a specific handler.\n     * <pre>disruptorWizard.handleExceptionsIn(eventHandler).with(exceptionHandler);</pre>\n     *\n     * @param eventHandler the event handler to set a different exception handler for.\n     * @return an ExceptionHandlerSetting dsl object - intended to be used by chaining the with method call.\n     */\n    public ExceptionHandlerSetting<T> handleExceptionsFor(final EventHandlerIdentity eventHandler)\n    {\n        return new ExceptionHandlerSetting<>(eventHandler, consumerRepository);\n    }\n\n    /**\n     * <p>Create a group of event handlers to be used as a dependency.","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/LMAX-Exchange/disruptor/blob/c871ca49826a6be7ada6957f6fbafcfecf7b1f87/src/main/java/com/lmax/disruptor/dsl/Disruptor.java#L215-L251","documentation":"Thrown by Disruptor.setDefaultExceptionHandler when the default exception handler slot has already been replaced by handleExceptionsWith(...). Internally the default is an ExceptionHandlerWrapper; handleExceptionsWith switches it to a concrete handler permanently, after which setDefaultExceptionHandler can no longer take effect, so the API fails fast rather than silently ignoring you.","triggerScenarios":"Calling disruptor.handleExceptionsWith(handler) and later disruptor.setDefaultExceptionHandler(other) on the same Disruptor instance (before start). The reverse order alone is fine; it is the combination in this order that throws.","commonSituations":"Library code calls handleExceptionsWith while application code also calls setDefaultExceptionHandler (or vice versa across versions); upgrading Disruptor 3.x -> 4.x where exception-handler configuration semantics were tightened; copy-pasted setup from two examples using different APIs.","solutions":["Use only one of the two APIs per Disruptor instance: prefer setDefaultExceptionHandler and per-handler overrides via handleExceptionsFor(...).with(...).","If a library you call uses handleExceptionsWith, configure your handlers with handleExceptionsFor instead of the global setter.","Audit startup code for both calls; remove the redundant one."],"exampleFix":"// before\ndisruptor.handleExceptionsWith(new FatalExceptionHandler());\ndisruptor.setDefaultExceptionHandler(new LogExceptionHandler<>()); // IllegalStateException\n\n// after\ndisruptor.setDefaultExceptionHandler(new LogExceptionHandler<>());\ndisruptor.handleExceptionsFor(myHandler).with(new FatalExceptionHandler());","handlingStrategy":"validation","validationCode":"// pick ONE style per Disruptor instance\ndisruptor.setDefaultExceptionHandler(defaultHandler);            // style A\n// or: disruptor.handleExceptionsWith(defaultHandler);           // style B (terminal)\n// per-handler overrides are always allowed:\ndisruptor.handleExceptionsFor(handlerA).with(specificHandler);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardise on setDefaultExceptionHandler in your codebase; ban handleExceptionsWith.","Audit third-party code that touches the same Disruptor for hidden handleExceptionsWith calls."],"tags":["disruptor","dsl","exception-handler","api-misuse","lifecycle"],"backgroundTag":null,"analyzedSha":"c871ca49826a6be7ada6957f6fbafcfecf7b1f87","analyzedAt":"2026-08-14T14:22:36.358Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}