{"record":{"id":"1aa4a32dca5b0265","repo":"github/copilot-sdk","slug":"request-cancelled-by-runtime-1aa4a3","errorCode":null,"errorMessage":"Request cancelled by runtime","messagePattern":"Request cancelled by runtime","errorType":"exception","errorClass":"OperationCanceledException","httpStatus":null,"severity":"warning","filePath":"dotnet/src/CopilotRequestHandler.cs","lineNumber":730,"sourceCode":"\n    /// <summary>\n    /// Request body bytes, yielded as they arrive. A cancel frame surfaces as an\n    /// <see cref=\"OperationCanceledException\"/> so the consumer's upstream call\n    /// is torn down.\n    /// </summary>\n    internal IAsyncEnumerable<ReadOnlyMemory<byte>> RequestBody => ReadBodyAsync(Abort.Token);\n\n    private async IAsyncEnumerable<ReadOnlyMemory<byte>> ReadBodyAsync(\n        [EnumeratorCancellation] CancellationToken cancellationToken = default)\n    {\n        while (await _body.Reader.WaitToReadAsync(cancellationToken).ConfigureAwait(false))\n        {\n            while (_body.Reader.TryRead(out var item))\n            {\n                if (item.Cancel)\n                {\n                    _body.Writer.TryComplete();\n                    throw new OperationCanceledException(\n                        item.CancelReason is null\n                            ? \"Request cancelled by runtime\"\n                            : $\"Request cancelled by runtime: {item.CancelReason}\");\n                }\n\n                if (item.End)\n                {\n                    _body.Writer.TryComplete();\n                    yield break;\n                }\n\n                if (item.Chunk is { Length: > 0 })\n                {\n                    yield return item.Chunk;\n                }\n            }\n        }\n    }","sourceCodeStart":712,"sourceCodeEnd":748,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/dotnet/src/CopilotRequestHandler.cs#L712-L748","documentation":"During LLM inference response streaming, the exchange consumes a cancel/end channel. When a cancel item arrives, the pending response body is completed and an OperationCanceledException is thrown to abort the request, with an optional reason from the runtime.","triggerScenarios":"The runtime cancels the in-flight LLM inference request while the client is reading response chunks — e.g. the originating RPC was aborted, a timeout fired, or the connection dropped and the runtime signalled cancellation.","commonSituations":"Upstream client disconnects mid-generation; request timeout policy cancels the exchange; user aborts a long-running completion; runtime shutdown cancels all active inferences.","solutions":["Wrap response consumption in try/catch for OperationCanceledException and treat it as normal cancellation","Check item.CancelReason (the exception message suffix) to identify why the runtime cancelled","Implement retry with backoff for cancellable inference requests when appropriate","Ensure long-running inference calls pass/observe cancellation tokens so client-side state stays consistent"],"exampleFix":"// before\nawait foreach (var chunk in exchange.ReadResponseAsync()) { Process(chunk); }\n// after\ntry { await foreach (var chunk in exchange.ReadResponseAsync()) { Process(chunk); } }\ncatch (OperationCanceledException) { /* runtime cancelled the request; cleanup */ }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await foreach (var chunk in exchange.ReadResponseAsync()) { ... } }\ncatch (OperationCanceledException) { /* expected on runtime cancellation */ }","preventionTips":["Always treat OperationCanceledException as a normal outcome for inference streams","Pass and honor CancellationToken in streaming loops","Inspect CancelReason in the exception message for diagnostics","Add retry with backoff for cancellable inference requests"],"tags":["cancellation","llm","streaming","dotnet"],"backgroundTag":"request-timeout","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"}