github/copilot-sdk · error · IllegalStateException

Client not connected. Call start() first.

Error message

Client not connected. Call start() first.

What it means

ensureConnected() guards every RPC-backed client method. If connectionFuture is null and autoStart is disabled, the client was never started, so it throws IllegalStateException telling the caller to invoke start() first.

Solutions

  1. Call client.start() before issuing any RPC calls
  2. Construct the client with autoStart enabled (options.isAutoStart()) if lazy start is desired
  3. Ensure dependency-injection setup invokes start() during initialization

Example fix

// before
CopilotClient client = new CopilotClient(options);
client.ping();
// after
CopilotClient client = new CopilotClient(options);
client.start().join();
client.ping();
Defensive patterns

Strategy: try-catch

Validate before calling

if (!started) { client.start().join(); started = true; }

Try / catch

try {
    client.someRpcCall();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("Call start() first")) {
        client.start().join();
    }
}

Prevention

When it happens

Trigger: Calling any RPC method (e.g. createSession, deleteSession, ping) on a CopilotClient built without auto-start before calling start().

Common situations: Constructing CopilotClient with default options where autoStart is off and skipping start(); refactoring that moved start() out of setup; DI frameworks instantiating the client without calling lifecycle methods.

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


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/c547cbf2ed3f1b6c. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/CopilotClient.java:1744

    /**
     * Subscribes to a specific session lifecycle event type.
     *
     * @param eventType
     *            the event type to listen for (use
     *            {@link com.github.copilot.rpc.SessionLifecycleEventTypes}
     *            constants)
     * @param handler
     *            a callback that receives events of the specified type
     * @return an AutoCloseable that, when closed, unsubscribes the handler
     */
    public AutoCloseable onLifecycle(String eventType, SessionLifecycleHandler handler) {
        return lifecycleManager.subscribe(eventType, handler);
    }

    private CompletableFuture<Connection> ensureConnected() {
        if (connectionFuture == null && !options.isAutoStart()) {
            throw new IllegalStateException("Client not connected. Call start() first.");
        }

        start();
        return connectionFuture;
    }

    /**
     * Closes this client using graceful shutdown semantics.
     * <p>
     * This method is intended for {@code try-with-resources} usage and blocks while
     * waiting for {@link #stop()} to complete, up to
     * {@link #AUTOCLOSEABLE_TIMEOUT_SECONDS} seconds. If shutdown fails or times
     * out, the error is logged at {@link Level#FINE} and the method returns.
     * <p>
     * This method is idempotent.
     *
     * @see #stop()
     * @see #forceStop()

View on GitHub (pinned to cd8cf15dc3)