Skip to content

Commit 85b6fed

Browse files
committed
Log warning for unhandled exceptions in default message handler
Transport errors that are not tied to a specific pending request (e.g., GET stream failures) were silently swallowed by the default message handler. Add a warning log so these exceptions are at least visible in logs as an observability safety net. Github-Issue: #1401
1 parent b3a8a7e commit 85b6fed

2 files changed

Lines changed: 12 additions & 1 deletion

File tree

src/mcp/client/session.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ async def __call__(
166166
async def _default_message_handler(
167167
message: RequestResponder[types.ServerRequest, types.ClientResult] | types.ServerNotification | Exception,
168168
) -> None:
169+
if isinstance(message, Exception):
170+
logger.warning("Unhandled exception in message handler: %s", message)
169171
await anyio.lowlevel.checkpoint()
170172

171173

tests/client/test_session.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
from mcp import MCPError
3939
from mcp.client import ClientRequestContext
4040
from mcp.client.client import Client
41-
from mcp.client.session import DEFAULT_CLIENT_INFO, ClientSession
41+
from mcp.client.session import DEFAULT_CLIENT_INFO, ClientSession, _default_message_handler
4242
from mcp.client.subscriptions import ToolsListChanged, listen
4343
from mcp.server import Server, ServerRequestContext
4444
from mcp.shared.direct_dispatcher import create_direct_dispatcher_pair
@@ -1030,6 +1030,15 @@ async def handler(msg: object) -> None:
10301030
assert "message_handler raised on transport exception" in caplog.text
10311031

10321032

1033+
@pytest.mark.anyio
1034+
async def test_default_message_handler_logs_unhandled_transport_exceptions(caplog: pytest.LogCaptureFixture):
1035+
"""The default handler has no per-request waiter to resolve, so a transport-level `Exception`
1036+
item (e.g. a GET stream failure) would vanish silently; it logs a warning as a safety net."""
1037+
with caplog.at_level("WARNING", logger="client"):
1038+
await _default_message_handler(RuntimeError("boom"))
1039+
assert "Unhandled exception in message handler" in caplog.text
1040+
1041+
10331042
@pytest.mark.anyio
10341043
async def test_message_handler_awaiting_session_traffic_on_transport_exception_completes():
10351044
"""A `message_handler` that awaits session traffic on a transport `Exception` item completes:

0 commit comments

Comments
 (0)