dotnet/runtime · warning · Error
OperationCanceledException
Error message
OperationCanceledException
What it means
While reading a streamed response in httpGetStreamedResponseBytes, once the reader reports chunk.done, if controller.isAborted is true the interop throws 'OperationCanceledException' so the .NET caller receives a proper cancellation rather than a clean zero-byte EOF. This maps to .NET's OperationCanceledException semantics.
Source
Thrown at src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts:262
const view = new Span(bufferPtr, bufferLength, MemoryViewType.Byte);
return wrapAsCancelablePromise(async () => {
await controller.responsePromise;
dotnetAssert.check(controller.response, "expected response");
if (!controller.response.body) {
// in FF when the verb is HEAD, the body is null
return 0;
}
if (!controller.streamReader) {
controller.streamReader = controller.response.body.getReader();
muteUnhandledRejection(controller.streamReader.closed);
}
if (!controller.currentStreamReaderChunk || controller.currentBufferOffset === undefined) {
controller.currentStreamReaderChunk = await controller.streamReader.read();
controller.currentBufferOffset = 0;
}
if (controller.currentStreamReaderChunk.done) {
if (controller.isAborted) {
throw new Error("OperationCanceledException");
}
return 0;
}
const remainingSource = controller.currentStreamReaderChunk.value.byteLength - controller.currentBufferOffset;
dotnetAssert.check(remainingSource > 0, "expected remainingSource to be greater than 0");
const bytesCopied = Math.min(remainingSource, view.byteLength);
const sourceView = controller.currentStreamReaderChunk.value.subarray(controller.currentBufferOffset, controller.currentBufferOffset + bytesCopied);
view.set(sourceView, 0);
controller.currentBufferOffset += bytesCopied;
if (remainingSource == bytesCopied) {
controller.currentStreamReaderChunk = undefined;
}
return bytesCopied;
});
}View on GitHub (pinned to 290d5ab72c)
Solutions
- Treat this as expected cancellation — handle OperationCanceledException in .NET rather than as a fault.
- If unexpected, check for an overly aggressive CancellationTokenSource timeout.
- Avoid aborting a controller whose response stream has already completed.
Example fix
// before: cancellation surfaces as an unhandled error
// after: handle expected cancellation
try { await responseStream.ReadAsync(buffer, ct); }
catch (OperationCanceledException) when (ct.IsCancellationRequested) { /* expected */ } Defensive patterns
Strategy: try-catch
Try / catch
try { await responseStream.ReadAsync(buffer, ct); }
catch (OperationCanceledException) when (ct.IsCancellationRequested) {
// expected cancellation, not a fault
} Prevention
- Distinguish cancellation from real errors in HttpClient exception handling.
- Do not fire cancellations spuriously near stream completion.
- Size CancellationTokenSource timeouts so they don't trigger right as a stream ends.
When it happens
Trigger: The response stream completed (or was cut) at the same moment the request was aborted via httpAbort/AbortController, so the interop surfaces cancellation to the .NET HttpClient.
Common situations: A CancellationToken fires exactly as the download stream ends; a client-side timeout triggering near response completion; explicit user cancel of a streaming download.
Related errors
- OperationCanceledException
- BrowserHttpWriteStream.Rejected
- BrowserHttpWriteStream.Rejected
- Please install `node-fetch` and `node-abort-controller` npm
- This browser doesn't support fetch API. Please use a modern
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/20a5b2d2a518f0bc.
Report an issue: GitHub.