github/copilot-sdk · error · RuntimeError
Copilot request response already finished.
Error message
Copilot request response already finished.
What it means
After the response has been finished (end_response/error called or the handler marked it finished), start_response() refuses to begin a new response on the same object. The `finished` flag is a terminal state in the response lifecycle: started -> writing -> finished. This prevents resurrecting a completed HTTP response on a request_id the runtime has already closed.
Solutions
- Check `response.finished` before attempting start_response(); do not start a response after the body stream has ended.
- Send errors before finishing: call error()/end only after all writes, and never start a new response afterwards.
- Create a new request/response exchange if you genuinely need to emit another HTTP response.
Example fix
// before
await response.write_response("chunk")
await response.end_response()
await response.start_response(500, "Error", {}) # finished
// after
if not response.finished:
await response.write_response("chunk")
await response.end_response()
else:
raise RuntimeError("response already completed; cannot restart") Defensive patterns
Strategy: validation
Validate before calling
if response.finished:
return # response already completed; nothing to start Type guard
def is_startable(response) -> bool:
return not getattr(response, "started", False) and not getattr(response, "finished", False) Try / catch
try:
await response.start_response(status, status_text, headers)
except RuntimeError as e:
if "already finished" in str(e):
logger.warning("attempted to restart finished response; ignoring")
else:
raise Prevention
- Send error/status changes before finishing the response, never after end/error.
- Order the lifecycle strictly: start -> writes -> end/error, with cleanup tasks cancelled before finishing.
- Check `finished` before any lifecycle call on a response you did not create.
When it happens
Trigger: Calling start_response() after end_response()/error() was called; calling start_response() on a response object that _finalize already completed; attempting to restart a response to send a retry or error status after the body was fully streamed.
Common situations: Middleware that tries to convert an in-flight response into an error response after the fact; handlers that run cleanup/finalization before the caller finishes writing; reusing a cached response object across retries.
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
- Copilot request response start() called twice.
- Copilot request response write() called before start().
- Copilot request response write() called after end()/error().
- Copilot request was cancelled by the runtime.
- Request cancelled by runtime
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/ae47b31fd36307ca.
Report an issue: GitHub.
Appendix: source
Thrown at python/copilot/copilot_request_handler.py:443
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,
status_text=status_text,
)
)
async def write_response(self, data: str | bytes) -> None:
if self.cancelled:
raise RuntimeError("Copilot request was cancelled by the runtime.")
if not self.started:
raise RuntimeError("Copilot request response write() called before start().")
if self.finished:
raise RuntimeError("Copilot request response write() called after end()/error().")
if isinstance(data, bytes):View on GitHub (pinned to cd8cf15dc3)