{"record":{"id":"c547cbf2ed3f1b6c","repo":"github/copilot-sdk","slug":"client-not-connected-call-start-first-c547cb","errorCode":null,"errorMessage":"Client not connected. Call start() first.","messagePattern":"Client not connected\\. Call start\\(\\) first\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/CopilotClient.java","lineNumber":1744,"sourceCode":"\n    /**\n     * Subscribes to a specific session lifecycle event type.\n     *\n     * @param eventType\n     *            the event type to listen for (use\n     *            {@link com.github.copilot.rpc.SessionLifecycleEventTypes}\n     *            constants)\n     * @param handler\n     *            a callback that receives events of the specified type\n     * @return an AutoCloseable that, when closed, unsubscribes the handler\n     */\n    public AutoCloseable onLifecycle(String eventType, SessionLifecycleHandler handler) {\n        return lifecycleManager.subscribe(eventType, handler);\n    }\n\n    private CompletableFuture<Connection> ensureConnected() {\n        if (connectionFuture == null && !options.isAutoStart()) {\n            throw new IllegalStateException(\"Client not connected. Call start() first.\");\n        }\n\n        start();\n        return connectionFuture;\n    }\n\n    /**\n     * Closes this client using graceful shutdown semantics.\n     * <p>\n     * This method is intended for {@code try-with-resources} usage and blocks while\n     * waiting for {@link #stop()} to complete, up to\n     * {@link #AUTOCLOSEABLE_TIMEOUT_SECONDS} seconds. If shutdown fails or times\n     * out, the error is logged at {@link Level#FINE} and the method returns.\n     * <p>\n     * This method is idempotent.\n     *\n     * @see #stop()\n     * @see #forceStop()","sourceCodeStart":1726,"sourceCodeEnd":1762,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/CopilotClient.java#L1726-L1762","documentation":"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.","triggerScenarios":"Calling any RPC method (e.g. createSession, deleteSession, ping) on a CopilotClient built without auto-start before calling start().","commonSituations":"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.","solutions":["Call client.start() before issuing any RPC calls","Construct the client with autoStart enabled (options.isAutoStart()) if lazy start is desired","Ensure dependency-injection setup invokes start() during initialization"],"exampleFix":"// before\nCopilotClient client = new CopilotClient(options);\nclient.ping();\n// after\nCopilotClient client = new CopilotClient(options);\nclient.start().join();\nclient.ping();","handlingStrategy":"try-catch","validationCode":"if (!started) { client.start().join(); started = true; }","typeGuard":null,"tryCatchPattern":"try {\n    client.someRpcCall();\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Call start() first\")) {\n        client.start().join();\n    }\n}","preventionTips":["Call start() in application bootstrap before any RPC usage","Enable autoStart in options if manual lifecycle management is error-prone","Wrap client creation + start() in a single factory method"],"tags":["lifecycle","not-connected","initialization"],"backgroundTag":"invalid-state-transition","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}