From cfb35b35c056501bd3b886b50b267da6cd315c89 Mon Sep 17 00:00:00 2001 From: moze Date: Wed, 6 May 2026 01:53:09 +0200 Subject: [PATCH] fix: suppress SSE client-disconnect noise in GlobalExceptionHandler AsyncRequestNotUsableException is thrown when the SSE client disconnects before the server finishes writing (normal: browser tab close, MCP client reconnect). The catch-all handler was logging it at ERROR level and then attempting to write a JSON ErrorResponse onto a text/event-stream response that no longer had a converter, producing a second spurious HttpMessageNotWritableException log entry. Fix: add a dedicated @ExceptionHandler(AsyncRequestNotUsableException) that logs at DEBUG only and returns void (no body). --- .../adapter/in/rest/GlobalExceptionHandler.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/trueref-adapters/src/main/java/com/trueref/adapter/in/rest/GlobalExceptionHandler.java b/trueref-adapters/src/main/java/com/trueref/adapter/in/rest/GlobalExceptionHandler.java index ed2d0ee..c66cd36 100644 --- a/trueref-adapters/src/main/java/com/trueref/adapter/in/rest/GlobalExceptionHandler.java +++ b/trueref-adapters/src/main/java/com/trueref/adapter/in/rest/GlobalExceptionHandler.java @@ -18,8 +18,9 @@ import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.resource.NoResourceFoundException; +import org.springframework.web.context.request.async.AsyncRequestNotUsableException; +import org.springframework.web.server.ResponseStatusException; /** Central translator from domain / validation exceptions to HTTP + {@link ErrorResponse} JSON. */ @RestControllerAdvice @@ -98,6 +99,14 @@ public class GlobalExceptionHandler { return status(HttpStatus.INTERNAL_SERVER_ERROR, ex); } + // Client disconnected from an SSE stream before the server finished writing. + // This is normal (browser tab closed, MCP client reconnected, etc.) — log at DEBUG only + // and return nothing; the response socket is already gone. + @ExceptionHandler(AsyncRequestNotUsableException.class) + public void handleClientDisconnect(AsyncRequestNotUsableException ex) { + log.debug("SSE client disconnected: {}", ex.getMessage()); + } + @ExceptionHandler(Exception.class) public ResponseEntity handleUnexpected(Exception ex) { log.error("unexpected error", ex);