cloudflare / cloudflare/workerd

HTMLRewriter cancellation emits a spurious uncaught rejection with TypeScript streams

Open
#7,239 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.