dotnet/runtime · error · Error
BrowserHttpWriteStream.Rejected
Error message
BrowserHttpWriteStream.Rejected
What it means
httpTransformStreamWrite() writes a chunk to a WritableStreamDefaultWriter used as the request body for a streaming fetch. If awaiting streamWriter.ready or streamWriter.write(copy) rejects (the underlying stream errored or the server aborted the upload), the original error is swallowed and replaced with this generic marker. The .NET side sees 'BrowserHttpWriteStream.Rejected'.
Solutions
- Wrap the streaming request in a try/catch and surface the cancellation/network failure to the user; the generic message means the stream was rejected, not the request payload itself.
- Check httpSupportsStreamingRequest() before attempting a streaming upload; if false, fall back to buffering the body (httpFetchBytes) instead of httpFetchStream.
- Verify the AbortController wasn't triggered prematurely (e.g. a timeout set too short) before the upload completed.
- On Safari or browsers without duplex fetch support, use a buffered (non-streaming) request body.
Example fix
// before: assume streaming upload always works
using var content = new StreamContent(largeStream);
await httpClient.PostAsync(url, content, ct);
// after: feature-detect and fall back
if (runtime.INTERNAL.httpSupportsStreamingRequest()) {
// streaming upload
} else {
// buffer the body into a byte[] and use HttpContent
} Defensive patterns
Strategy: try-catch
Validate before calling
// Feature-detect streaming request support before choosing the upload path.
import { httpSupportsStreamingRequest } from "./http";
function planUpload(body: Uint8Array): "stream" | "buffer" {
return httpSupportsStreamingRequest() ? "stream" : "buffer";
} Type guard
null
Try / catch
try {
await runtime.INTERNAL.httpFetchStream(controller, url, hNames, hVals, oNames, oVals);
} catch (e) {
if (e?.message === "BrowserHttpWriteStream.Rejected") {
// transport rejected the stream: network/abort/unsupported duplex
// fall back to a buffered request or surface to the user
} else throw e;
} Prevention
- Gate streaming uploads on httpSupportsStreamingRequest(); fall back to buffered bodies.
- Set request timeouts generously enough for large uploads; avoid premature AbortController firing.
- Do not use streaming uploads on browsers known to lack duplex fetch (older Safari).
- Surface stream-rejection as a transport failure and let the caller decide on retry.
When it happens
Trigger: Calling HttpClient with a streaming request body (httpFetchStream) and writing a chunk whose underlying writer rejected. Triggers: server closed the connection mid-upload, the AbortController fired, the browser rejected the duplex stream (e.g. unsupported in Safari), or a network failure during request body upload.
Common situations: Uploading large/streaming request bodies with HttpClient.PostAsync + StreamContent; Safari which does not fully support duplex fetch streams; server-side early response/reset (RST_STREAM) that aborts the request writer; AbortController token triggered during upload.
Related errors
- BrowserHttpWriteStream.Rejected
- OperationCanceledException
- Failed to download , Status Code
- Failed to load resource
- Failed to load WebAssembly module. HTTP status
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/07caaa5837523574.
Report an issue: GitHub.
Appendix: source
Thrown at src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts:110
} catch (err) {
// ignore
}
}
export function httpTransformStreamWrite(controller: HttpController, bufferPtr: VoidPtr, bufferLength: number): ControllablePromise<void> {
commonAsserts(controller);
dotnetAssert.check(bufferLength > 0, "expected bufferLength > 0");
// the bufferPtr is pinned by the caller
const view = new Span(bufferPtr, bufferLength, MemoryViewType.Byte);
const copy = view.slice() as Uint8Array;
return wrapAsCancelablePromise(async () => {
dotnetAssert.check(controller.streamWriter, "expected streamWriter");
dotnetAssert.check(controller.responsePromise, "expected fetch promise");
try {
await controller.streamWriter.ready;
await controller.streamWriter.write(copy);
} catch (ex) {
throw new Error("BrowserHttpWriteStream.Rejected");
}
});
}
export function httpTransformStreamClose(controller: HttpController): ControllablePromise<void> {
dotnetAssert.check(controller, "expected controller");
return wrapAsCancelablePromise(async () => {
dotnetAssert.check(controller.streamWriter, "expected streamWriter");
dotnetAssert.check(controller.responsePromise, "expected fetch promise");
try {
await controller.streamWriter.ready;
await controller.streamWriter.close();
} catch (ex) {
throw new Error("BrowserHttpWriteStream.Rejected");
}
});
}
View on GitHub (pinned to 60108ba66e)