{"record":{"id":"07caaa5837523574","repo":"dotnet/runtime","slug":"browserhttpwritestream-rejected-07caaa","errorCode":null,"errorMessage":"BrowserHttpWriteStream.Rejected","messagePattern":"BrowserHttpWriteStream\\.Rejected","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts","lineNumber":110,"sourceCode":"    } catch (err) {\n        // ignore\n    }\n}\n\nexport function httpTransformStreamWrite(controller: HttpController, bufferPtr: VoidPtr, bufferLength: number): ControllablePromise<void> {\n    commonAsserts(controller);\n    dotnetAssert.check(bufferLength > 0, \"expected bufferLength > 0\");\n    // the bufferPtr is pinned by the caller\n    const view = new Span(bufferPtr, bufferLength, MemoryViewType.Byte);\n    const copy = view.slice() as Uint8Array;\n    return wrapAsCancelablePromise(async () => {\n        dotnetAssert.check(controller.streamWriter, \"expected streamWriter\");\n        dotnetAssert.check(controller.responsePromise, \"expected fetch promise\");\n        try {\n            await controller.streamWriter.ready;\n            await controller.streamWriter.write(copy);\n        } catch (ex) {\n            throw new Error(\"BrowserHttpWriteStream.Rejected\");\n        }\n    });\n}\n\nexport function httpTransformStreamClose(controller: HttpController): ControllablePromise<void> {\n    dotnetAssert.check(controller, \"expected controller\");\n    return wrapAsCancelablePromise(async () => {\n        dotnetAssert.check(controller.streamWriter, \"expected streamWriter\");\n        dotnetAssert.check(controller.responsePromise, \"expected fetch promise\");\n        try {\n            await controller.streamWriter.ready;\n            await controller.streamWriter.close();\n        } catch (ex) {\n            throw new Error(\"BrowserHttpWriteStream.Rejected\");\n        }\n    });\n}\n","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/http.ts#L92-L128","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: assume streaming upload always works\nusing var content = new StreamContent(largeStream);\nawait httpClient.PostAsync(url, content, ct);\n\n// after: feature-detect and fall back\nif (runtime.INTERNAL.httpSupportsStreamingRequest()) {\n    // streaming upload\n} else {\n    // buffer the body into a byte[] and use HttpContent\n}","handlingStrategy":"try-catch","validationCode":"// Feature-detect streaming request support before choosing the upload path.\nimport { httpSupportsStreamingRequest } from \"./http\";\n\nfunction planUpload(body: Uint8Array): \"stream\" | \"buffer\" {\n  return httpSupportsStreamingRequest() ? \"stream\" : \"buffer\";\n}","typeGuard":"null","tryCatchPattern":"try {\n  await runtime.INTERNAL.httpFetchStream(controller, url, hNames, hVals, oNames, oVals);\n} catch (e) {\n  if (e?.message === \"BrowserHttpWriteStream.Rejected\") {\n    // transport rejected the stream: network/abort/unsupported duplex\n    // fall back to a buffered request or surface to the user\n  } else throw e;\n}","preventionTips":["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."],"tags":["http","streaming","upload","network","fetch"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}