github/copilot-sdk · error · RuntimeError
Copilot request response used after RPC connection closed.
Error message
Copilot request response used after RPC connection closed.
What it means
_require_rpc fetches the ServerLlmInferenceApi RPC channel backing the response object; if the connection has been closed the channel is None. Any response use after that point (start_response, write_response, end_response, error_response) raises RuntimeError because responses can no longer be delivered over the dead RPC connection.
Solutions
- Check connection state (or wrap calls in try/except RuntimeError) before using the response object
- Complete all response writes while the RPC connection is alive; buffer and resend across a new connection if needed
- Treat connection-closed during response as terminal: discard the response and let the client retry the request
- Keep a reconnect mechanism and re-issue the whole request rather than reusing the stale response object
Example fix
// before
await response.start_response(200) # raises after disconnect
// after
try:
await response.start_response(200)
await response.write_response(data)
await response.end_response()
except RuntimeError as e:
if "RPC connection closed" in str(e):
logger.warning("dropped response: connection closed") Defensive patterns
Strategy: try-catch
Validate before calling
def can_respond(response) -> bool:
try:
return response._get_server_rpc() is not None
except Exception:
return False Try / catch
try:
await response.start_response(200)
await response.write_response(data)
await response.end_response()
except RuntimeError as e:
if "RPC connection closed" in str(e):
logger.warning("response aborted: RPC closed")
else:
raise Prevention
- Finish all response writes before the connection can close
- Never cache response objects across reconnects
- Monitor connection state and abort response generation on disconnect
- Retry by re-issuing the full request on a fresh connection
When it happens
Trigger: Calling start_response/write_response/end_response/error_response after the underlying RPC connection to the Copilot server has closed — e.g. the handler finishes after disconnect, or the response is stored and used later.
Common situations: Responding to a request after the client/server connection dropped, holding response objects across reconnects, slow response writing that outlives the connection, or shutdown racing with response generation.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- Copilot request response already finished.
- Copilot request response write() called after end()/error().
- Copilot request response used after RPC connection closed.
- The in-process runtime connection is closed.
- Client not connected; call start() first
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/8430bdb7f6325de2.
Report an issue: GitHub.
Appendix: source
Thrown at python/copilot/copilot_request_handler.py:431
"""Fill in the request context once the matching start frame arrives."""
self.session_id = params.session_id
self.agent_id = params.agent_id
self.parent_agent_id = params.parent_agent_id
self.interaction_type = params.interaction_type
self.method = params.method
self.url = params.url
self.headers = params.headers
transport = params.transport
self.transport = transport.value if transport is not None else "http"
@property
def request_body(self) -> _BodyQueue:
return self._queue
def _require_rpc(self) -> ServerLlmInferenceApi:
rpc = self._get_server_rpc()
if rpc is None:
raise RuntimeError("Copilot request response used after RPC connection closed.")
return rpc
async def start_response(
self,
status: int,
status_text: str | None = None,
headers: LlmInferenceHeaders | None = None,
) -> None:
if self.started:
raise RuntimeError("Copilot request response start() called twice.")
if self.finished:
raise RuntimeError("Copilot request response already finished.")
self.started = True
await self._require_rpc().http_response_start(
LlmInferenceHTTPResponseStartRequest(
headers=headers or {},
request_id=self.request_id,
status=status,View on GitHub (pinned to cd8cf15dc3)