@@ -209,6 +209,7 @@ <h2>Table of Contents</h2>
209209
210210< li > < a href ="#Event_Handler_Exceptions "> Event Handler Exceptions</ a > </ li >
211211< li > < a href ="#Custom_Event_Error_Handler "> Custom Event Error Handler</ a > </ li >
212+ < li > < a href ="#Event_Error_Policy "> Event Error Policy</ a > </ li >
212213</ ul > </ li >
213214</ ul > < hr /> </ section > < section > < a id ="Custom_Tools "> </ a >
214215< h2 > Custom Tools</ h2 >
@@ -528,11 +529,14 @@ <h2>Error Handling</h2>
528529 });
529530</ code > </ pre > < section > < a id ="Event_Handler_Exceptions "> </ a >
530531< h3 > Event Handler Exceptions</ h3 >
531- < p > If an event handler throws an exception, the SDK catches it, logs it at
532- < code > SEVERE</ code > level, and continues dispatching to remaining handlers. This means
533- one faulty handler will never block others from receiving events:</ p >
532+ < p > If an event handler registered via < code > session.on()</ code > throws an exception, the SDK
533+ catches it and logs it at < code > WARNING</ code > level. By default, dispatch < strong > stops</ strong > after
534+ the first handler error (< code > PROPAGATE_AND_LOG_ERRORS</ code > policy). You can opt in to
535+ continue dispatching despite errors using < code > SUPPRESS_AND_LOG_ERRORS</ code > :</ p >
536+
537+ < pre class ="prettyprint "> < code class ="language-java "> // With SUPPRESS_AND_LOG_ERRORS, second handler still runs
538+ session.setEventErrorPolicy(EventErrorPolicy.SUPPRESS_AND_LOG_ERRORS);
534539
535- < pre class ="prettyprint "> < code class ="language-java "> // This handler throws, but the second handler still runs
536540session.on(AssistantMessageEvent.class, msg -> {
537541 throw new RuntimeException("bug in handler 1");
538542});
@@ -542,17 +546,11 @@ <h3>Event Handler Exceptions</h3>
542546 System.out.println(msg.getData().getContent());
543547});
544548</ code > </ pre >
545- < blockquote >
546-
547- < p > < strong > Note:</ strong > This exception isolation behavior is consistent with the Node.js,
548- Go, and Python Copilot SDKs, which all catch handler errors per-handler. The
549- .NET SDK is an exception — handler errors propagate there and can prevent
550- subsequent handlers from running.</ p >
551- </ blockquote > </ section > < section > < a id ="Custom_Event_Error_Handler "> </ a >
549+ < p > Errors are < strong > always logged</ strong > at < code > WARNING</ code > level regardless of the policy or
550+ whether a custom error handler is set.</ p > </ section > < section > < a id ="Custom_Event_Error_Handler "> </ a >
552551< h3 > Custom Event Error Handler</ h3 >
553- < p > By default, handler exceptions are logged at < code > SEVERE</ code > level using
554- < code > java.util.logging</ code > . You can replace this with a custom
555- < code > EventErrorHandler</ code > to integrate with your own logging, metrics, or
552+ < p > Set a custom < code > EventErrorHandler</ code > for additional handling beyond the default
553+ logging — such as metrics, alerts, or integration with external
556554error-reporting systems:</ p >
557555
558556< pre class ="prettyprint "> < code class ="language-java "> session.setEventErrorHandler((event, exception) -> {
@@ -563,11 +561,51 @@ <h3>Custom Event Error Handler</h3>
563561</ code > </ pre >
564562< p > The error handler receives both the event that was being dispatched and the
565563exception that was thrown. If the error handler itself throws, that exception
566- is silently caught and logged to prevent cascading failures.</ p >
567- < p > Pass < code > null</ code > to restore the default logging behavior:</ p >
564+ is caught and logged at < code > SEVERE</ code > , and dispatch is stopped to prevent cascading
565+ failures.</ p >
566+ < p > Pass < code > null</ code > to use only the default logging behavior:</ p >
568567
569568< pre class ="prettyprint "> < code class ="language-java "> session.setEventErrorHandler(null);
570- </ code > </ pre > </ section > </ section > </ section > </ main >
569+ </ code > </ pre > </ section > < section > < a id ="Event_Error_Policy "> </ a >
570+ < h3 > Event Error Policy</ h3 >
571+ < p > By default, the SDK propagates errors and stops dispatch on the first handler
572+ error (< code > EventErrorPolicy.PROPAGATE_AND_LOG_ERRORS</ code > ). You can opt in to
573+ < strong > suppress</ strong > errors so that all handlers execute despite errors:</ p >
574+
575+ < pre class ="prettyprint "> < code class ="language-java "> session.setEventErrorPolicy(EventErrorPolicy.SUPPRESS_AND_LOG_ERRORS);
576+ </ code > </ pre >
577+ < p > The < code > EventErrorHandler</ code > (if set) is always invoked regardless of the policy —
578+ the policy only controls whether remaining handlers execute after the error
579+ handler returns. Errors are always logged at < code > WARNING</ code > level.</ p >
580+ < table class ="table table-striped ">
581+ < thead >
582+ < tr class ="a ">
583+ < th > Policy</ th >
584+ < th > Behavior</ th > </ tr > </ thead > < tbody >
585+ < tr class ="b ">
586+ < td > < code > PROPAGATE_AND_LOG_ERRORS</ code > (default)</ td >
587+ < td > Log the error; dispatch halts after the first error</ td > </ tr >
588+ < tr class ="a ">
589+ < td > < code > SUPPRESS_AND_LOG_ERRORS</ code > </ td >
590+ < td > Log the error; all remaining handlers execute</ td > </ tr > </ tbody >
591+ </ table >
592+
593+ < p > You can combine both for full control:</ p >
594+
595+ < pre class ="prettyprint "> < code class ="language-java "> // Log errors via custom handler and suppress (continue dispatching)
596+ session.setEventErrorPolicy(EventErrorPolicy.SUPPRESS_AND_LOG_ERRORS);
597+ session.setEventErrorHandler((event, ex) ->
598+ logger.error("Handler failed, continuing: {}", ex.getMessage(), ex));
599+ </ code > </ pre >
600+ < p > Or switch policies dynamically:</ p >
601+
602+ < pre class ="prettyprint "> < code class ="language-java "> // Start strict (propagate errors, stop dispatch)
603+ session.setEventErrorPolicy(EventErrorPolicy.PROPAGATE_AND_LOG_ERRORS);
604+
605+ // Later, switch to lenient mode (suppress errors, continue)
606+ session.setEventErrorPolicy(EventErrorPolicy.SUPPRESS_AND_LOG_ERRORS);
607+ </ code > </ pre >
608+ < p > See < a href ="apidocs/com/github/copilot/sdk/EventErrorPolicy.html "> EventErrorPolicy</ a > and < a href ="apidocs/com/github/copilot/sdk/EventErrorHandler.html "> EventErrorHandler</ a > Javadoc for details.</ p > </ section > </ section > </ section > </ main >
571609 </ div >
572610 </ div >
573611 < hr />
0 commit comments