{"record":{"id":"f9a1ef1bc87fdaf7","repo":"PrefectHQ/fastmcp","slug":"server-did-not-start-listening-on-host-port-wi","errorCode":null,"errorMessage":"Server did not start listening on {host}:{port} within {timeout} seconds","messagePattern":"Server did not start listening on (.+?):(.+?) within (.+?) seconds","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/utilities/tests.py","lineNumber":162,"sourceCode":"    proc.terminate()\n    proc.join(timeout=5)\n    if proc.is_alive():\n        # If it's still alive, then force kill it\n        proc.kill()\n        proc.join(timeout=2)\n        if proc.is_alive():\n            raise RuntimeError(\"Server process failed to terminate even after kill\")\n\n\nasync def _wait_for_port(host: str, port: int, timeout: float = 5.0) -> None:\n    \"\"\"Poll until a TCP connection to `host:port` is accepted, or raise on timeout.\"\"\"\n    deadline = time.monotonic() + timeout\n    while True:\n        try:\n            _, writer = await asyncio.open_connection(host, port)\n        except (ConnectionRefusedError, OSError):\n            if time.monotonic() >= deadline:\n                raise RuntimeError(\n                    f\"Server did not start listening on {host}:{port} \"\n                    f\"within {timeout} seconds\"\n                ) from None\n            await asyncio.sleep(0.001)\n        else:\n            writer.close()\n            with suppress(ConnectionResetError, BrokenPipeError):\n                await writer.wait_closed()\n            return\n\n\n@asynccontextmanager\nasync def run_server_async(\n    server: FastMCP,\n    port: int | None = None,\n    transport: Literal[\"http\", \"streamable-http\", \"sse\"] = \"http\",\n    path: str = \"/mcp\",\n    host: str = \"127.0.0.1\",","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/utilities/tests.py#L144-L180","documentation":"_wait_for_port repeatedly attempts an asyncio TCP connection to host:port; if the deadline passes while connections are still refused, it raises RuntimeError announcing the server never started listening. The `from None` suppresses the chained ConnectionRefusedError/OSError for a clean message.","triggerScenarios":"Calling run_server_async (or any path using _wait_for_port) against a host:port where no server binds within the timeout (default 5s) — server not started yet, crashed, bound to a different interface, or wrong port passed.","commonSituations":"Wrong host (localhost resolving to ::1 while server binds 127.0.0.1); server crash during startup; slow CI machines exceeding the 5s window; connecting before the server coroutine actually starts.","solutions":["Confirm the server actually started and binds the expected host/port before/while polling","Use 127.0.0.1 explicitly instead of localhost to avoid IPv6 mismatch","Increase the timeout parameter if startup is legitimately slow","Check server logs for startup exceptions"],"exampleFix":"// before\nawait _wait_for_port(\"localhost\", 8000)  # may resolve to ::1\n\n// after\nawait _wait_for_port(\"127.0.0.1\", 8000, timeout=10.0)","handlingStrategy":"retry","validationCode":"import socket\ntry:\n    socket.create_connection((\"127.0.0.1\", port), timeout=1).close()\nexcept OSError:\n    ...  # port not open yet — start server before waiting","typeGuard":null,"tryCatchPattern":"try:\n    await _wait_for_port(\"127.0.0.1\", port, timeout=10.0)\nexcept RuntimeError as e:\n    print(f\"server not up: {e}\")  # inspect server logs before proceeding","preventionTips":["Use 127.0.0.1, not localhost, to avoid IPv6 mismatch","Increase timeout on slow CI","Confirm the server binds before polling","Watch server stderr for startup crashes"],"tags":["network","timeout","testing","asyncio"],"backgroundTag":"connection-refused","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}