Skip to content

Guard worker fetch relay against null-body-status Response throw - #243

Open
ryanbr wants to merge 1 commit into
masterfrom
fix/relay-null-body-status
Open

Guard worker fetch relay against null-body-status Response throw#243
ryanbr wants to merge 1 commit into
masterfrom
fix/relay-null-body-status

Conversation

@ryanbr

@ryanbr ryanbr commented Jun 17, 2026

Copy link
Copy Markdown
Owner

Problem

The worker fetch relay reconstructs the worker's fetch responses on the worker side:

const response = new Response(responseData.body, { status: responseData.status,});

new Response(body, { status }) throws a RangeError when a non-null body is paired with a null-body status (101 / 204 / 205 / 304). The main-thread relay supplies the body as await response.text() — which is an empty string '' (not null) for those statuses. So a 304 Not Modified or 204 returned through the relay (e.g. a conditional playlist/token request) makes the worker-side reconstruction throw: the relayed fetch never resolves, and the worker hangs on it until the relay timeout fires.

Fix

Drop the body for null-body statuses before constructing the Response:

const _nullBodyStatus = responseData.status === 101 || responseData.status === 204 || responseData.status === 205 || responseData.status === 304;
const response = new Response(_nullBodyStatus ? null : responseData.body, { status: responseData.status,});

Status/statusText/headers are unchanged, as is the url/redirected/type post-assignment the IVS WASM validation needs.

Scope

  • Real-but-low-frequency: most relay fetches are 200; 304 is the realistic trigger. The relay timeout already bounds the hang, so this is a robustness fix, not a crash.
  • Mirrors GosuDRM/TTV-AB v9.7.1 ("responses with status 101, 204, 205, or 304 are now rebuilt without a body") and v9.9.0 ("exhausted token fetches return a real network-error response instead of throwing from the Response constructor") — shared relay lineage, upstream hit it in the field.
  • vaft release pair; mirrored to the testing pair (direct to master, v658). npx acorn clean on all four files. No version bump (accumulates under ## Unreleased).

🤖 Generated with Claude Code

The relay reconstructs responses on the worker side via
new Response(body, { status }). The Response constructor throws a
RangeError when a non-null body is paired with a null-body status
(101/204/205/304) — and the main-thread relay passes body as
await response.text(), which is '' (empty string, not null) for those
statuses. So a 304/204 through the relay (e.g. a conditional
playlist/token request) would throw, the relayed fetch would never
resolve, and the worker would hang until the relay timeout.

Drop the body for null-body statuses. Mirrors GosuDRM/TTV-AB
v9.7.1 / v9.9.0 (shared relay lineage; upstream hit it in the field).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ryanbr added a commit that referenced this pull request Jun 17, 2026
… throw

Mirror of PR #243 (release pair). The worker-side relay rebuilt responses
via new Response(body, { status }); a 304/204 through the relay carries an
empty-string body (not null), so the Response constructor threw and the
relayed fetch hung until timeout. Drop the body for null-body statuses
(101/204/205/304). Mirrors TTV-AB v9.7.1 / v9.9.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant