cloudflare / cloudflare/workerd
HTMLRewriter cancellation emits a spurious uncaught rejection with TypeScript streams
- Dominant language
- C++
- Stars
- 8.7k
- Forks
- 739
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 174
Description
## Description
With `typescript_implemented_streams`, canceling an `HTMLRewriter` output after a read can produce a spurious `Uncaught (in promise) Error: done early` even though `reader.cancel()` is awaited.
The rejection is not delivered to Worker `unhandledrejection` listeners. It is reported through `Worker::Lock::logUncaughtException`, so it appears in tail-worker traces and inspector output. The C++ streams implementation does not report it.
## Reproduction
PR #7178 adds `cancelReachesSourceAfterNextChunk` in `src/tests/streams/htmlrewriter/rewrite-streams.js`. The test:
1. Transforms a queued-backed `ReadableStream`.
2. Reads the first transformed chunk.
3. Awaits cancellation of the transformed body.
4. Enqueues another source chunk to wake the parked rewriter pump.
5. Awaits the source cancellation.
After the next source chunk wakes the pump, cancellation reaches the source and the TypeScript streams path emits the uncaught-rejection log.
## Expected behavior
A cancellation whose returned promise is handled should not be reported as an uncaught exception.
## Suspected path
The failure path in `pumpQueuedTsStream()` in `src/workerd/api/js-readable-stream.c++` aborts the sink, cancels the draining reader, and rethrows. A promise on this path may remain unhandled.
## Reference
[Review discussion](https://github.com/cloudflare/workerd/pull/7178#discussion_r3930141272)
Contributor guide
Assessment
This issue has not been assessed yet.