Skip to content

RuntimeError: Event loop is closed warning during subprocess transport cleanup in pytest #2792

@jlowin

Description

@jlowin

Description

When using Client with StdioMCPServer in pytest, we get warnings during test teardown:

PytestUnraisableExceptionWarning: Exception ignored in: <function BaseSubprocessTransport.__del__ at ...>

Traceback (most recent call last):
  File ".../asyncio/base_subprocess.py", line 126, in __del__
    self.close()
  ...
  File ".../asyncio/base_events.py", line 515, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

Reproduction

import pytest
from fastmcp import Client
from fastmcp.mcp_config import StdioMCPServer

@pytest.mark.asyncio
async def test_stdio_client():
    server = StdioMCPServer(command="python", args=["-m", "some_mcp_server"])
    async with Client(server) as client:
        # do something
        pass
    # Warning appears after test completes

Environment

  • Python 3.10 on Linux (works fine on macOS)
  • fastmcp 3.0.x
  • pytest-asyncio

Analysis

The issue is that asyncio's BaseSubprocessTransport has a __del__ method that calls self._loop.call_soon(), which fails if the event loop is already closed. During pytest teardown, the loop closes before all subprocess transport references are garbage collected.

Things we tried that didn't help:

  • Setting keep_alive=False on StdioTransport
  • Explicit del client after context exit
  • await asyncio.sleep(0) to flush callbacks
  • gc.collect() while loop is still open

Possible solutions

  1. In StdioTransport.close(), explicitly wait for the subprocess to terminate and clean up the transport before returning
  2. Use subprocess.Popen directly instead of asyncio subprocess (avoids the BaseSubprocessTransport.__del__ issue)
  3. Store a reference to the transport and call transport.close() synchronously in a way that doesn't require the event loop

Related

StdioMCPServer.to_transport() doesn't pass through the keep_alive parameter - it always defaults to True on the created StdioTransport. (Noted this is fixed in a future version.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working. Reports of errors, unexpected behavior, or broken functionality.clientRelated to the FastMCP client SDK or client-side functionality.tests

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions