PrefectHQ/fastmcp · error · RuntimeError

FastMCP server instance is no longer available

Error message

FastMCP server instance is no longer available

What it means

get_server() stores the server as a weak reference. This RuntimeError is thrown when the reference exists but the referent has been garbage-collected — i.e. the server was set in the contextvar and later deleted while code still holds the context. It is distinct from the 'no server in context' case: a server was active, but its lifetime ended.

Source

Thrown at fastmcp_slim/fastmcp/server/dependencies.py:481

    Returns:
        The active FastMCP server

    Raises:
        RuntimeError: If no server in context
    """
    resolver = _worker_server_resolver
    if resolver is not None:
        worker_server = resolver()
        if worker_server is not None:
            return worker_server

    server_ref = _current_server.get()
    if server_ref is None:
        raise RuntimeError("No FastMCP server instance in context")
    server = server_ref()
    if server is None:
        raise RuntimeError("FastMCP server instance is no longer available")
    return server


async def get_session(session_id: str) -> Session:
    """Resolve and validate a `Session` for an explicit `session_id`.

    Pair with a `session_id: SessionId` tool argument (the agent obtains an id
    from `create_session` and passes it back). For a single per-user bucket with
    nothing for the agent to pass, inject `session: UserSession` instead.

    State is keyed by `(principal, session_id)`: the authenticated principal is
    the isolation wall and `session_id` organizes sessions within it. The id must
    have been minted by `create_session` under the current principal; an id that
    was never created, or created under a different principal, raises
    `InvalidSession` rather than resolving to a fresh empty bucket (the specific
    reason is logged at debug level, never returned to the caller).

    Like `get_server()`, this resolves through the task-aware server, so it needs

View on GitHub (pinned to 1f02114297)

Solutions

  1. Keep a strong reference to the FastMCP instance for as long as dependent code runs (module-level or app-lifetime variable).
  2. Ensure background tasks complete (await them) before the server object goes out of scope.
  3. Set the server contextvar again around the work if it must run after the original context ended.

Example fix

// before
def make():
    mcp = FastMCP("x")
    asyncio.create_task(worker())  # mcp can be GC'd
    return None
// after
MCP = FastMCP("x")  # module-level strong ref
asyncio.create_task(worker())
Defensive patterns

Strategy: type-guard

Type guard

server = None
try:
    server = get_server()
except RuntimeError:
    server = None
if server is None:
    # weakref died or no context: rebuild or fail explicitly
    raise RuntimeError("server unavailable; keep a strong reference")

Try / catch

try:
    server = get_server()
except RuntimeError:
    server = default_server  # module-level strong reference

Prevention

When it happens

Trigger: Calling get_server() after the FastMCP instance that set _current_server was garbage-collected — e.g. a temporary server object created inside a function went out of scope while an async task referencing it continues running.

Common situations: Background tasks outliving a short-lived server instance; building a server in a local scope and returning only a reference to a handler; holding contextvars across server teardown in tests.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/db27cecac1eeaa6e. Report an issue: GitHub.