github/copilot-sdk · error · IllegalStateException

Session is not connected — RPC client is unavailable

Error message

Session is not connected — RPC client is unavailable

What it means

CopilotSession.getRpc() lazily publishes the SessionRpc handle from the rpc field; if rpc is still null the session has no live connection to the server and the method throws IllegalStateException instead of returning a unusable RPC client.

Solutions

  1. Await session readiness (e.g. a ready/initialized future) before calling getRpc()
  2. Catch IllegalStateException and retry after the session reconnects
  3. Check whether the session was terminated/reconnected; obtain a fresh CopilotSession if so
  4. Serialize access so session setup completes before worker threads call RPC APIs

Example fix

// before
session.getRpc().invoke("task", req);
// after
session.whenReady().join(); // ensure handshake done
session.getRpc().invoke("task", req);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!session.isConnected() /* or readiness future not done */) { awaitReadiness(session); }

Try / catch

try {
    session.getRpc();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("not connected")) {
        // wait for reconnect or recreate the session
    }
}

Prevention

When it happens

Trigger: Calling session.getRpc() (directly or via metadata/task/setModel/sendMcpAuthResponse/interest/updateSessionOptionsForMode) before the session's initialization handshake finished or after the underlying connection dropped and rpc was nulled.

Common situations: Touching getRpc() immediately after createSession returns on a pre-registered/resumed session; using a session after connection loss; calling session APIs from a thread that races session initialization.

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/26ba82547cea84c8. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/CopilotSession.java:405

     * Returns the typed RPC client for this session.
     * <p>
     * Provides strongly-typed access to all session-level API namespaces. The
     * {@code sessionId} is injected automatically into every call.
     * <p>
     * Example usage:
     *
     * <pre>{@code
     * var agents = session.getRpc().agent.list().get();
     * }</pre>
     *
     * @return the session-scoped typed RPC client (never {@code null})
     * @throws IllegalStateException
     *             if the session is not connected
     * @since 1.0.0
     */
    public SessionRpc getRpc() {
        if (rpc == null) {
            throw new IllegalStateException("Session is not connected — RPC client is unavailable");
        }
        SessionRpc current = sessionRpc;
        if (current == null) {
            synchronized (this) {
                current = sessionRpc;
                if (current == null) {
                    sessionRpc = current = new SessionRpc(rpc::invoke, sessionId);
                }
            }
        }
        return current;
    }

    /**
     * Sets a custom error handler for exceptions thrown by event handlers.
     * <p>
     * When an event handler registered via {@link #on(Consumer)} or
     * {@link #on(Class, Consumer)} throws an exception during event dispatch, the

View on GitHub (pinned to cd8cf15dc3)