{"record":{"id":"7035ed968775375e","repo":"github/copilot-sdk","slug":"copilot-request-response-used-after-rpc-connection","errorCode":null,"errorMessage":"Copilot request response used after RPC connection closed.","messagePattern":"Copilot request response used after RPC connection closed\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nodejs/src/copilotRequestHandler.ts","lineNumber":640,"sourceCode":"    }\n\n    async errorResponse(error: { message: string; code?: string }): Promise<void> {\n        if (this.#finished) {\n            return;\n        }\n        this.#finished = true;\n        await this.#rpc().llmInference.httpResponseChunk({\n            requestId: this.requestId,\n            data: \"\",\n            end: true,\n            error: { message: error.message, code: error.code },\n        });\n    }\n\n    #rpc(): ServerRpc {\n        const r = this.#getServerRpc();\n        if (!r) {\n            throw new Error(\"Copilot request response used after RPC connection closed.\");\n        }\n        return r;\n    }\n}\n\nconst FORBIDDEN_REQUEST_HEADERS = new Set([\n    \"host\",\n    \"connection\",\n    \"content-length\",\n    \"transfer-encoding\",\n    \"keep-alive\",\n    \"upgrade\",\n    \"proxy-connection\",\n    \"te\",\n    \"trailer\",\n]);\n\nasync function buildFetchRequest(exchange: CopilotRequestExchange): Promise<Request> {","sourceCodeStart":622,"sourceCodeEnd":658,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/nodejs/src/copilotRequestHandler.ts#L622-L658","documentation":"Responses are delivered to the runtime via an RPC connection obtained through #rpc(). If that connection has closed (or was never available), the handler cannot forward httpResponseStart/Chunk calls. #rpc() throws this error whenever the server RPC accessor returns nothing.","triggerScenarios":"The WebSocket/RPC connection to the Copilot runtime closes while the handler is still emitting the response — calling startResponse, writeResponse, endResponse, or errorResponse afterwards.","commonSituations":"Long-running handlers that outlive the connection (runtime restart, network drop, client process exit); slow work followed by response emission after the session ended.","solutions":["Check connection state before starting response emission and skip/abort the response if the RPC connection is down.","Keep handler processing short so the response is emitted within the connection's lifetime.","Wrap the whole emit sequence in try/catch and treat this as an unrecoverable transport failure — log and return.","Investigate why the RPC connection closed (runtime exit, timeout, network) if this occurs routinely.","Enable reconnect/keepalive at the client/runtime layer if supported by your setup."],"exampleFix":"// before\nawait longCompute();\nawait handler.startResponse({ status: 200 }); // may throw if RPC closed\n// after\nif (!handler.rpcConnected) return; // skip emission when transport is gone\nawait longCompute();\nawait handler.startResponse({ status: 200 });","handlingStrategy":"try-catch","validationCode":"function isRpcClosed(e: unknown): boolean {\n  return e instanceof Error && e.message.includes('used after RPC connection closed');\n}\n// check before emitting\nif (typeof handler.rpcConnected === 'boolean' && !handler.rpcConnected) return;","typeGuard":null,"tryCatchPattern":"try {\n  await handler.startResponse({ status: 200 });\n  await handler.writeResponse(body);\n  await handler.endResponse();\n} catch (e) {\n  if (isRpcClosed(e)) { log.warn('response dropped: RPC connection closed'); return; }\n  throw e;\n}","preventionTips":["Emit responses promptly; avoid long compute between request and response.","Wrap the entire emit sequence so partial responses don't leave dangling state.","Monitor RPC connection health/lifetime for long-running handlers.","Investigate recurring connection drops (timeouts, restarts, network)."],"tags":["network","websocket","rpc","connection-closed"],"backgroundTag":"connection-refused","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"}