You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(ext/http): surface errors thrown while streaming a Deno.serve body (#35104)
## Summary
A `Deno.serve` response whose body is a `ReadableStream` /
`TransformStream`
that throws **while being drained** swallowed the error completely. The
error
was flattened to a bare message that was only used to abort the
underlying
transport, so:
- the client saw a truncated response, and
- **nothing on the server implicated the faulty callback**.
The motivating example from #19867 — a typo'd `value.toUppperCase()`
inside a
transformer — failed silently with no stack trace anywhere.
## What happens now
```
TypeError: value.toUppperCase is not a function
at Object.transform (file:///.../main.ts:27:31)
at Object.invokeCallbackFunction (ext:deno_webidl/00_webidl.js:1154:16)
at transformAlgorithm (ext:deno_web/06_streams.js:3998:14)
...
```
The stack trace pointing at the throwing transformer is printed, and the
server stays alive for subsequent requests.
## How
- `resourceForReadableStream` (`ext/web/06_streams.js`) gains an
optional
`onError` callback. When the stream errors while being drained into the
resource, the callback is invoked with the **original error object**
(stack
included) *before* it is flattened to a string for the Rust transport.
Other
callers (`fetch`, `cache`) pass no callback and are unaffected.
- `Deno.serve` (`ext/http/00_serve.ts`) passes a callback that routes
the error
through the server's error handler (`onError`). The default handler logs
a
stack trace; a user-provided `onError` can observe it for
logging/metrics.
### Note on returning 500
The issue also asks whether a 500 should be returned. By the time the
body
stream starts producing chunks the response status and headers have
already
been committed to the wire, so the response can no longer be changed and
the
value returned from `onError` cannot be used. The error is therefore
surfaced
for observability only; the connection is still aborted (so the client
sees a
truncated body) and the server keeps serving. Returning a 500 would only
be
possible by buffering the entire streamed body before sending headers,
which
would defeat streaming.
## Test
`tests/specs/serve/stream_body_error` — a serve handler whose streaming
body
throws in a `TransformStream` transformer must print a stack trace
implicating
the transformer and keep the server alive for a follow-up request.
Fixes#19867Closesdenoland/divybot#552
Co-authored-by: divybot <divybot@users.noreply.github.com>
Co-authored-by: Divy Srivastava <me@littledivy.com>
0 commit comments