github/copilot-sdk · error · RuntimeError
Server port not available
Error message
Server port not available
What it means
RuntimeError raised by CopilotClient._connect_via_tcp when the runtime port is missing or unknown, so there is no host:port endpoint to dial. Per the method's docstring it fires when the server port is not available or the connection fails; typically the spawned CLI never reported its listening port during startup.
Solutions
- Use the normal start/connect flow so the port announcement is awaited before TCP connect
- If connecting to an external server, configure host/port explicitly instead of relying on the announced port
- Verify the client is not in stdio/FFI mode when calling the TCP connect path
- Recover from failed startups by creating a fresh client instance
Example fix
// before await client._connect_via_tcp() # _runtime_port never set -> RuntimeError // after await client.start() # waits for 'listening on port N', sets _runtime_port await client._connect_via_tcp()
Defensive patterns
Strategy: validation
Validate before calling
if not getattr(client, "_runtime_port", None):
await client.start() # ensure port announcement completed first Type guard
def has_port(client) -> bool:
return bool(getattr(client, "_runtime_port", 0)) Try / catch
try:
await client._connect_via_tcp()
except RuntimeError as e:
if "Server port not available" in str(e):
await client.start()
await client._connect_via_tcp()
else:
raise Prevention
- Always run the full startup flow before TCP connect
- Don't mix stdio/FFI mode with the TCP connect path
- Provide an explicit host/port when connecting to an external server
- Recreate the client after failed startups instead of partial reconnects
When it happens
Trigger: Calling _connect_via_tcp() before the port-announcement wait completed, after TCP startup failed to set _runtime_port, or when configured for a mode (stdio/FFI) that never sets a runtime port.
Common situations: Mixing transports: spawning the CLI in stdio mode then connecting via TCP; skipping the port wait step; a previous startup error left _runtime_port unset; manually constructing the client and calling connect internals out of order.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Server port not available
- CLI process not started
- CLI child process was unexpectedly started in parent…
- Session not found
- Copilot request response already finished.
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/fd1bb591e0f10657.
Report an issue: GitHub.
Appendix: source
Thrown at python/copilot/client.py:4646
)
register_client_session_api_handlers(self._client, self._get_client_session_handlers)
self._register_client_global_handlers()
# Start listening for messages
loop = asyncio.get_running_loop()
self._client.start(loop)
async def _connect_via_tcp(self) -> None:
"""
Connect to the CLI server via TCP socket.
Creates a TCP connection to the server at the configured host and port.
Raises:
RuntimeError: If the server port is not available or connection fails.
"""
if not self._runtime_port:
raise RuntimeError("Server port not available")
# Create a TCP socket connection with timeout. create_connection resolves
# both IPv4 and IPv6 addresses instead of forcing AF_INET.
import socket
# Connection timeout constant
TCP_CONNECTION_TIMEOUT = 10 # seconds
try:
tcp_connect_start = time.perf_counter()
logger.info(
"CopilotClient._connect_via_tcp connecting to CLI server",
extra={"host": self._actual_host, "port": self._runtime_port},
)
sock = socket.create_connection(
(self._actual_host, self._runtime_port), timeout=TCP_CONNECTION_TIMEOUT
)
sock.settimeout(None) # Remove timeout after connectionView on GitHub (pinned to cd8cf15dc3)