microsoft/semantic-kernel · error · FunctionExecutionException

Failed to enter context manager.

Error message

Failed to enter context manager.

What it means

Thrown by MCPPluginBase.connect (mcp.py:308) as a FunctionExecutionException, wrapping any exception during connect() that is NOT a KernelPluginInvalidConfigurationError. The connect() flow spawns _inner_connect as a task and waits on a ready_event; only config errors are re-raised verbatim, everything else (and event-wait failures) is wrapped here and forces a close().

Source

Thrown at python/semantic_kernel/connectors/mcp.py:308

    async def __aexit__(
        self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: Any
    ) -> None:
        """Exit the context manager."""
        await self.close()

    async def connect(self) -> None:
        """Connect to the MCP server."""
        ready_event = asyncio.Event()
        try:
            self._current_task = asyncio.create_task(self._inner_connect(ready_event))
            await ready_event.wait()
        except KernelPluginInvalidConfigurationError:
            ready_event.clear()
            raise
        except Exception as ex:
            ready_event.clear()
            await self.close()
            raise FunctionExecutionException("Failed to enter context manager.") from ex

    async def close(self) -> None:
        """Disconnect from the MCP server."""
        if self._stop_event:
            # Signal the stop event, which asks the _inner_connect
            # method to close the session with the exit stack
            self._stop_event.set()
        if self._current_task:
            # After, the signal, we wait for it to close the exit stack.
            await self._current_task
            self._current_task = None
        self.session = None

    async def _inner_connect(self, ready_event: asyncio.Event) -> None:
        if not self.session:
            try:
                transport = await self._exit_stack.enter_async_context(self.get_mcp_client())
            except Exception as ex:

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Inspect the chained __cause__ (from ex) for the real underlying error before acting.
  2. Ensure connect() is called exactly once and awaited fully; use the async context manager (async with plugin:) to avoid races.
  3. If load_tools/load_prompts is the culprit, set load_tools=False/load_prompts=False and load manually after connect.
  4. Avoid cancelling the connect task; if you must, expect this wrapper.

Example fix

# before
await plugin.connect()  # may race if called twice

# after (use the context manager)
async with plugin:
    result = await plugin.call_tool("foo", arg=1)
Defensive patterns

Strategy: try-catch

Validate before calling

# ensure single, awaited connect before use
async def safe_connect(plugin) -> bool:
    if plugin.session is not None:
        return True
    await plugin.connect()
    return plugin.session is not None

Type guard

def plugin_is_connected(plugin) -> bool:
    return getattr(plugin, "session", None) is not None

Try / catch

from semantic_kernel.exceptions.function_exceptions import FunctionExecutionException

try:
    async with plugin:
        await plugin.call_tool("foo")
except FunctionExecutionException as ex:
    if "Failed to enter context manager" in str(ex):
        # inspect ex.__cause__; likely asyncio cancellation or a runtime error
        log.error("connect failed: %r", ex.__cause__)

Prevention

When it happens

Trigger: An asyncio.CancelledError or unexpected runtime error during ready_event.wait(); a failure inside _inner_connect that surfaces as a generic Exception rather than the dedicated config errors at mcp.py:329/345/352; double-connect races; the task being cancelled externally.

Common situations: Calling connect() concurrently from two coroutines; cancelling the connect task mid-handshake; an unhandled error in load_tools()/load_prompts() (which run after session init inside _inner_connect); event-loop closure during connect.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/ff57e8b9bc9200f8. Report an issue: GitHub.