github/copilot-sdk · error · IOException
LLM inference response writeResponse() called after…
Error message
LLM inference response writeResponse() called after endResponse()/errorResponse()
What it means
This IOException is thrown when writeResponseText/writeResponseBinary is called after the exchange has already been finished via endResponse() or errorResponse(). Once finished, the response stream is complete and no further chunks can be sent over the RPC connection; the library rejects the write to keep the protocol consistent.
Solutions
- Reorder code so all chunks are written before endResponse()/errorResponse()
- Remove any writes in finally/cleanup blocks after the response is finished
- Track completion state in your handler and skip writes once endResponse has been called
- Catch this IOException and log rather than retrying — the exchange cannot be reopened
Example fix
// before
exchange.writeResponseText("done");
exchange.endResponse();
// after
exchange.writeResponseText("done");
exchange.endResponse(); // no writes after this point Defensive patterns
Strategy: validation
Validate before calling
if (!responseFinished) {
exchange.writeResponseText(chunk);
} Try / catch
try {
exchange.writeResponseText(chunk);
} catch (IOException e) {
if (String.valueOf(e.getMessage()).contains("after endResponse")) {
LOG.warning("skipped write after response finished");
return;
}
throw e;
} Prevention
- Mark the exchange finished in your own state and skip writes afterwards
- No writes inside finally blocks once endResponse ran
- Finish the response exactly once, at a single call site
- Cancel async tasks that may write after finalize
When it happens
Trigger: Calling writeResponseText or writeResponseBinary after endResponse() or errorResponse() returned — e.g., writing a final summary chunk after closing the stream, or an async callback firing after the response was finalized.
Common situations: Async/continuation code that writes a trailing chunk after endResponse; duplicated finalize logic where endResponse is called then more writes happen in a finally block; retried handlers re-invoking write after the first attempt completed the response.
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
- LLM inference response writeResponse() called before…
- LLM inference request was cancelled by the runtime
- LLM inference response used after RPC connection closed
- CLI process not started
- CLI child process was unexpectedly started in parent…
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/7536eabec4390b5b.
Report an issue: GitHub.
Appendix: source
Thrown at java/sdk/src/main/java/com/github/copilot/LlmInferenceExchange.java:238
return;
}
finished = true;
}
var error = new LlmInferenceHttpResponseChunkError(message, code);
var params = new LlmInferenceHttpResponseChunkParams(requestId, "", null, Boolean.TRUE, error);
join(api().httpResponseChunk(params));
}
private void writeChunk(String data, boolean binary) throws IOException {
synchronized (lock) {
if (cancelled) {
throw new IOException("LLM inference request was cancelled by the runtime");
}
if (!started) {
throw new IOException("LLM inference response writeResponse() called before startResponse()");
}
if (finished) {
throw new IOException(
"LLM inference response writeResponse() called after endResponse()/errorResponse()");
}
}
var params = new LlmInferenceHttpResponseChunkParams(requestId, data, binary ? Boolean.TRUE : null,
Boolean.FALSE, null);
join(api().httpResponseChunk(params));
}
private ServerLlmInferenceApi api() throws IOException {
ServerLlmInferenceApi api = rpcSupplier.get();
if (api == null) {
throw new IOException("LLM inference response used after RPC connection closed");
}
return api;
}
private static <T> T join(CompletableFuture<T> future) throws IOException {
try {View on GitHub (pinned to cd8cf15dc3)