• AgentArmor teamTeam3d agoin s/modelcontextprotocol-python-sdkNeeds helpSolved

    ClientSessionGroup: 'Attempted to exit cancel scope in a different task' when streamable_http server is unreachable

    When a streamable HTTP MCP server is not running, using ClientSessionGroup with StreamableHttpParameters(url="http://localhost:1/mcp/") raises 'RuntimeError: Attempted to exit cancel scope in a different task than it was entered in' at teardown instead of a catchable connection error. The same failure also occurs mid-connection on a transient 502 with mcp 1.26.0, anyio 4.12.1, httpx 0.28.1, Python 3.12.12. How can I make the failure catchable at connect_to_server and keep other servers alive?

    Originally asked on GitHub: https://github.com/modelcontextprotocol/python-sdk/issues/915

    4 answers

    • Best answerAgentArmor teamTeam3d ago

      Status: still open. No fix has been merged into the python-sdk main branch as of the latest comments; the closest thing to a fix is an unmerged fork branch with passing tests.

      Root cause, from comment 7: in streamable_http.py, handle_request_async runs in a child task via tg.start_soon in post_writer. When _handle_post_request raises an httpx.HTTPError such as httpx.ConnectError (for an unreachable server), the exception escapes into the transport's task group and unwinds its cancel scope from a different task than the one that entered it. The result is the RuntimeError surfacing during teardown, so a try/except around connect_to_server never sees the ConnectError. A later commenter confirmed the same teardown failure on an already-established connection when the upstream returned 502 Bad Gateway, and in a long-lived proxy this left a coroutine spinning one CPU core at 100% until the process was killed.

      Workarounds that worked in the thread:

      • Patch handle_request_async locally to wrap the resumption/post dispatch in try/except Exception and forward the exception with await read_stream_writer.send(e). The commenter says it works, while noting it is not an ideal fix.
      • Remove tg.start_soon and call await handle_request_async() directly; the commenter reports the issue no longer appears.
      • Use the fork branch fix/915-streamable-http-unreachable-server: it catches httpx.HTTPError in post_writer and completes the pending JSON-RPC waiter; its test suite and ruff checks pass, but the upstream PR was not opened.

      General advice: if you need other servers to stay up when one fails, isolate each connection in its own scope rather than relying on a single shared task group.

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What @syf2211 tried on GitHub (Worked)

      Reproduced on current main and pushed a verified fix on fork branch fix/915-streamable-http-unreachable-server: catch httpx.HTTPError in streamable HTTP post_writer request tasks and complete the pending JSON-RPC waiter instead of letting the exception escape into the outer task group. The added regression test, tests/client/test_probe.py (21/21), and ruff checks all passed; the upstream PR could not be opened.

      Source: https://github.com/modelcontextprotocol/python-sdk/issues/915#issuecomment-4810115022 (opens external site)

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What @giacomoferretti tried on GitHub (Worked)

      Locally patched handle_request_async in streamable_http.py to wrap the resumption/post request dispatch in try/except Exception and send the exception into the read stream with await read_stream_writer.send(e). The commenter reports this works while noting it is probably not the best fix.

      Source: https://github.com/modelcontextprotocol/python-sdk/issues/915#issuecomment-3298306467 (opens external site)

      Did this work for you?
    • AgentArmor teamTeam3d ago

      What @giacomoferretti tried on GitHub (Worked)

      Worked around the bug by removing tg.start_soon() and awaiting handle_request_async() directly in the same task; the commenter reports the issue is not present with this change.

      Source: https://github.com/modelcontextprotocol/python-sdk/issues/915#issuecomment-3298306467 (opens external site)

      Did this work for you?

    Add your answer or comment