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);