github/copilot-sdk · warning · CancellationException

Request cancelled by runtime

Error message

Request cancelled by runtime

What it means

LlmInferenceExchange.readFrame() consumes items from the response body queue; when it pulls a CANCEL sentinel it re-arms it in the queue (so later reads fail fast too) and throws CancellationException('Request cancelled by runtime'). This signals that the runtime cancelled the LLM inference request while the reader was pumping body frames.

Solutions

  1. Treat CancellationException as a normal, expected termination: catch it around the pump/drain loop and clean up without logging as an error.
  2. Stop issuing follow-up work for the request once cancellation is observed — the sentinel is re-armed so reads keep failing fast.
  3. If cancellation is unexpected, trace why the runtime cancelled (timeouts, abort signals) and adjust those policies.

Example fix

// before
while ((frame = exchange.readFrame()) != null) { consume(frame); }
// after
try {
    while ((frame = exchange.readFrame()) != null) { consume(frame); }
} catch (CancellationException e) {
    LOG.fine("Inference stream cancelled by runtime");
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    while ((frame = exchange.readFrame()) != null) { consume(frame); }
} catch (CancellationException e) {
    cleanup(); // expected: runtime cancelled the request
}

Prevention

When it happens

Trigger: The runtime cancels the inference request (user abort, timeout, client disconnect) while readFrame() — called from pump() or drainBody() — is waiting on or draining the body BlockingQueue (LlmInferenceExchange.java:156).

Common situations: User presses stop in a streaming chat UI; the host cancels a long-running generation; a downstream timeout tears down the request mid-stream and the pump loop observes the cancellation sentinel.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/2a92cf3c1879035d. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/LlmInferenceExchange.java:156

        body.add(new BodyItem(ItemKind.CANCEL, null, false));
    }

    /**
     * Reads the next request body frame, blocking until one is available.
     *
     * @return the next frame, or {@code null} when the body has ended
     * @throws InterruptedException
     *             if interrupted while waiting
     * @throws CancellationException
     *             if the runtime cancelled the request
     */
    BodyFrame readFrame() throws InterruptedException {
        BodyItem item = body.take();
        switch (item.kind()) {
            case CANCEL -> {
                // Re-arm the sentinel so subsequent reads keep failing fast.
                body.add(item);
                throw new CancellationException("Request cancelled by runtime");
            }
            case END -> {
                body.add(item);
                return null;
            }
            default -> {
                return new BodyFrame(item.data(), item.binary());
            }
        }
    }

    byte[] drainBody() throws InterruptedException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        BodyFrame frame;
        while ((frame = readFrame()) != null) {
            out.writeBytes(frame.data());
        }
        return out.toByteArray();

View on GitHub (pinned to cd8cf15dc3)