github/copilot-sdk · error
Server port not available
Error message
Server port not available
What it means
connectViaTcp connects to a CLI server over a TCP socket, but this.runtimePort is unset, so there is no port to dial. The library throws synchronously instead of attempting a connection to an undefined endpoint. It means the server/port discovery step never ran or failed before the TCP connect.
Solutions
- Start the CLI server first and await the step that assigns runtimePort before calling connect().
- Check server startup logs for port allocation or bind failures that left runtimePort unset.
- Create a fresh client instance if a previous stop() cleared the port, rather than reconnecting on a stale instance.
- Verify firewall/localhost binding so the server can actually acquire a port in your environment.
Example fix
// before
const client = new CopilotClient({ hosting: 'tcp', ... });
await client.connect(); // runtimePort not yet assigned
// after
const client = new CopilotClient({ hosting: 'tcp', ... });
await client.start(); // boots server, assigns port
await client.connect(); Defensive patterns
Strategy: try-catch
Validate before calling
if (!client.isServerReady?.()) {
throw new Error('TCP server not ready: start the runtime before connecting');
} Try / catch
try {
await client.start();
await client.connect();
} catch (err) {
if (err instanceof Error && err.message === 'Server port not available') {
// inspect server startup logs; recreate client and retry start()
}
throw err;
} Prevention
- Await the server-start step before connect() in TCP mode.
- Capture and check server startup logs for bind/port failures.
- Add a readiness probe (port reachable) before connecting.
- Create a fresh client after stop() instead of reconnecting on a stale port.
When it happens
Trigger: Calling connect() on a TCP-hosted CopilotClient before the runtime server (or its port) has been assigned — server startup failed, port discovery was skipped, or the port was cleared during teardown/restart.
Common situations: Server process failed to boot (port allocation failure, crashed binary) before connect(); calling connect() immediately after construction without awaiting the server-start step; reusing a stopped client whose runtimePort was reset.
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
- Failed to connect to CLI server at
- failed to close socket
- server port not available
- failed to connect to CLI server at
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/6078abafdd50a3d2.
Report an issue: GitHub.
Appendix: source
Thrown at nodejs/src/client.ts:2960
}
// Create JSON-RPC connection over stdin/stdout
this.messageWriter = new TeardownResilientStreamMessageWriter(process.stdout);
this.connection = createMessageConnection(
new StreamMessageReader(process.stdin),
this.messageWriter
);
this.attachConnectionHandlers();
this.connection.listen();
}
/**
* Connect to the CLI server via TCP socket
*/
private async connectViaTcp(): Promise<void> {
if (!this.runtimePort) {
throw new Error("Server port not available");
}
return new Promise((resolve, reject) => {
this.socket = new Socket();
const connectionTimeout = setTimeout(() => {
this.socket?.destroy();
reject(new Error("Timeout connecting to CLI server"));
}, 10000);
this.socket.connect(this.runtimePort!, this.actualHost, () => {
clearTimeout(connectionTimeout);
// Create JSON-RPC connection
this.messageWriter = new TeardownResilientStreamMessageWriter(this.socket!);
this.connection = createMessageConnection(
new StreamMessageReader(this.socket!),
this.messageWriter
);View on GitHub (pinned to cd8cf15dc3)