Skip to content

node:net: route exceptions thrown by socket event listeners to uncaughtException - #34066

Open
robobun wants to merge 5 commits into
mainfrom
farm/d202105f/net-data-listener-throw
Open

node:net: route exceptions thrown by socket event listeners to uncaughtException#34066
robobun wants to merge 5 commits into
mainfrom
farm/d202105f/net-data-listener-throw

Conversation

@robobun

@robobun robobun commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Fixes #34064
Fixes #29761

Problem

An exception thrown synchronously from a user listener invoked inside a native socket callback (e.g. a throwing 'data' listener on a net.Socket) escaped into the native dispatch, which routes a throwing handler to the socket's error callback. That is the documented behavior for the public Bun.listen/Bun.connect API, but node:net is layered on those handlers, so the thrown exception was delivered to the socket's 'error' listeners as if it were a socket error. With an 'error' listener registered (as pg always does), the exception silently disappeared instead of reaching uncaughtException like in Node.

const c = net.connect(port);
c.on("error", () => {});                 // swallows the throw below on Bun
c.on("data", () => { throw new Error("boom"); });   // Node: uncaughtException

Fix

Wrap the node:net handler tables (SocketHandlers, ServerHandlers, SocketHandlers2) so an exception escaping a handler is rethrown on process.nextTick, reaching the uncaughtException machinery, and the socket is torn down (the callback was interrupted mid-dispatch, so its stream state is unreliable; this matches the teardown the previous error routing performed). Genuine socket errors (ECONNRESET, ECONNREFUSED, ...) still flow through the error handler to socket.emit("error") unchanged. The public Bun.listen/Bun.connect API is not affected.

Surfacing these exceptions unmasked a second bug, fixed in the second commit: uws_res_end_without_body unconditionally wrote Connection: close plus a header terminator even when the chunked body had already started, so ServerResponse#destroy() on an in-flight chunked response injected Connection: close\r\n\r\n into the middle of the body. Clients parse that as Parse Error: Invalid character in chunk size (HPE_INVALID_CHUNK_SIZE); previously that parse-error throw was itself swallowed by the routing bug above. Node sends nothing extra on destroy, and now Bun's wire bytes match Node's.

Related: #29762 fixed the lifecycle-listener cases ('connect'/'ready'/'connection') of the same class and deferred the 'data' path; the handler-table wrapping here covers the dispatch boundary those paths also run through.

Verification

New tests in test/js/node/net/node-net.test.ts (each fails on an unfixed build):

  • throwing 'data' listener with a socket 'error' listener reaches uncaughtException; the 'error' listener is not invoked
  • same for an accepted server-side socket
  • without an uncaughtException handler the process exits 1 with the thrown error
  • the pg shape from the issue: re-emitting 'error' on a listenerless EventEmitter from a 'data' listener reaches uncaughtException

New test in test/js/node/http/node-http.test.ts: destroying a chunked response mid-stream sends exactly the written chunk frame, no header bytes in the body.

test/js/node/net/, test/js/node/tls/, test/js/node/http/, test/js/bun/http/serve.test.ts and the abort/destroy/close/error/keepalive subset of test/js/node/test/parallel/test-http-* pass with the change (remaining failures also fail on main in the same environment: broken localhost/DNS resolution, and test-http-agent-keepalive.js which fails on an unmodified debug build).


no test proof · iteration 1 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/js/node/net/node-net.test.ts

@robobun

robobun commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 7:15 AM PT - Jul 13th, 2026

@robobun, your commit dd852ddaa32426d5fe77a8db3b9af5928dcd7f34 passed in Build #72441! 🎉


🧪   To try this PR locally:

bunx bun-pr 34066

That installs a local version of the PR into your bun-34066 executable, so you can run:

bun-34066 --bun

@github-actions

Copy link
Copy Markdown
Contributor

Found 3 issues this PR may fix:

  1. node:net does not catch errors inside the 'data' callback #29761 - Exact same bug: exceptions thrown inside a node:net 'data' callback are swallowed instead of reaching uncaughtException
  2. ERR_INCOMPLETE_CHUNKED_ENCODING with Next.js app using Bun in Docker behind NGINX proxy #19789 - Chunked encoding corruption (ERR_INCOMPLETE_CHUNKED_ENCODING) behind NGINX proxy matches the uws_res_end_without_body fix that prevented writing Connection: close bytes mid-body
  3. TypeError in node:net when using neo4j-driver #21226 - TypeError in node:net drain handler (socket.data is undefined) when using neo4j-driver, possibly caused by misrouted exceptions corrupting socket state

If this is helpful, copy the block below into the PR description to auto-close these issues on merge.

Fixes #29761
Fixes #19789
Fixes #21226

🤖 Generated with Claude Code

@robobun

robobun commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Checked the three suggestions:

@github-actions

Copy link
Copy Markdown
Contributor

This PR may be a duplicate of:

  1. net: route throws from socket lifecycle listeners to uncaughtException #29762 - Also wraps node:net socket handler callbacks to route user-listener exceptions to uncaughtException instead of the socket error handler
  2. Don't write Connection: close into an in-flight chunked response body #32036 - Also guards uws_res_end_without_body against injecting Connection: close header bytes into an already-started chunked response body

🤖 Generated with Claude Code

@robobun

robobun commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Not a duplicate of either, but there is real overlap worth spelling out:

Comment thread test/js/node/http/node-http.test.ts Outdated
Comment thread src/js/node/net.ts
robobun added 2 commits July 13, 2026 12:27
…ughtException

An exception thrown synchronously from a user listener invoked inside a
native socket callback (e.g. a throwing 'data' listener) escaped into the
native dispatch, which routes a throwing handler to the socket's error
callback. That behavior is correct for the public Bun.listen/Bun.connect
API, but for node:net it delivered the thrown exception to the socket's
'error' listeners as if it were a socket error, so it never reached
uncaughtException the way it does in Node.

Wrap the node:net handler tables so an exception escaping a handler is
rethrown on process.nextTick, reaching the uncaughtException machinery,
and the socket is torn down (its dispatch was interrupted mid-callback,
matching the teardown the previous error routing performed). Genuine
socket errors still flow through the error handler unchanged.

Fixes #34064
Fixes #29761
… response

uws_res_end_without_body unconditionally wrote "Connection: close" and a
header terminator even when the chunked body had already started, so
ServerResponse#destroy() on an in-flight chunked response injected
"Connection: close\r\n\r\n" into the middle of the body. Clients parse
that as an invalid chunk size (HPE_INVALID_CHUNK_SIZE). The bug was
previously masked on the client side because the resulting parse error
throw was swallowed by the socket error routing fixed in the previous
commit.

Skip the header writes once HTTP_WRITE_CALLED is set (the header section
is terminated and body bytes are on the wire). HTTP_WROTE_CONTENT_LENGTH_HEADER
must not gate this: the file-route HEAD path sets it for a plain header
line and relies on this function to write the terminating CRLF.
@robobun
robobun force-pushed the farm/d202105f/net-data-listener-throw branch from 7784c74 to 5f57e0f Compare July 13, 2026 12:27
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The changes guard native socket callbacks against escaping exceptions, adjust TLS client-error handling, and prevent HTTP response termination from writing headers after body output begins. Regression tests cover socket exception propagation, TLS events, and chunked response termination.

Changes

Socket exception handling and TLS behavior

Layer / File(s) Summary
Guard native socket callbacks
src/js/node/net.ts
Socket handler tables and the onread data callback now schedule uncaught rethrows and terminate available socket handles when callbacks throw.
Adjust TLS handshake error emission
src/js/node/net.ts, test/js/node/tls/node-tls-cert.test.ts
TLS handshake control flow and certificate tests now verify that an admitted unverified client does not produce a tlsClientError event.
Validate socket exception behavior
test/js/node/net/node-net.test.ts
Subprocess tests cover client and server data listeners, missing uncaughtException handlers, unhandled errors, and onread callbacks.

HTTP response termination

Layer / File(s) Summary
Gate response termination writes
src/uws_sys/libuwsockets.cpp
SSL and non-SSL response termination paths avoid emitting connection headers and CRLF bytes once body output has started.
Validate chunked response output
test/js/node/http/node-http.test.ts
A raw TCP regression test verifies that destroying a chunked response mid-stream does not add header bytes to the body.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: routing node:net socket listener exceptions to uncaughtException.
Description check ✅ Passed The description covers what the PR does and how it was verified, with detailed problem/fix/verification sections.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/js/node/net.ts`:
- Around line 263-270: Condense the explanatory comment above the native socket
callback handling to no more than three lines, retaining only that thrown
user-listener exceptions must surface as uncaughtException and that the socket
is torn down afterward. Remove the detailed API and dispatch rationale from the
comment.

In `@src/uws_sys/libuwsockets.cpp`:
- Around line 1341-1346: Trim the comment near the write/header-state logic in
src/uws_sys/libuwsockets.cpp lines 1341-1346 to no more than three lines while
preserving its essential rationale. In test/js/node/http/node-http.test.ts lines
3753-3755, remove all regression-test commentary except the issue URL.

In `@test/js/node/net/node-net.test.ts`:
- Around line 1067-1174: Update the “exceptions thrown from socket event
listeners” suite to run its independent subprocess tests concurrently, using the
repository’s supported concurrent test or describe API. Preserve each test’s
existing fixture setup, assertions, and subprocess behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6aa15294-75cd-4cc3-a564-03666f9f3461

📥 Commits

Reviewing files that changed from the base of the PR and between 8f1a954 and 5f57e0f.

📒 Files selected for processing (4)
  • src/js/node/net.ts
  • src/uws_sys/libuwsockets.cpp
  • test/js/node/http/node-http.test.ts
  • test/js/node/net/node-net.test.ts

Comment thread src/js/node/net.ts Outdated
Comment thread src/uws_sys/libuwsockets.cpp Outdated
Comment thread test/js/node/net/node-net.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/js/node/net.ts (1)

1492-1501: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not swallow onread callback exceptions before protectHandler.

onread.callback() is still converted into self.emit("error", e), so an attached 'error' listener bypasses rethrowUncaught() and socket teardown. Let the exception escape to the wrapper, or invoke the same rethrow/terminate helper here.

Proposed fix
-        try {
-          onread.callback(buffer.length, buffer);
-        } catch (e) {
-          self.emit("error", e);
-        }
+        onread.callback(buffer.length, buffer);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/js/node/net.ts` around lines 1492 - 1501, Update the data handler’s
onread.callback invocation inside protectHandler so callback exceptions are not
converted to self.emit("error", e); let them propagate to protectHandler or
invoke the established rethrow/termination helper, preserving socket teardown
and uncaught-error behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/js/node/net.ts`:
- Around line 1492-1501: Update the data handler’s onread.callback invocation
inside protectHandler so callback exceptions are not converted to
self.emit("error", e); let them propagate to protectHandler or invoke the
established rethrow/termination helper, preserving socket teardown and
uncaught-error behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bc97c24b-8bf9-432b-b22d-f301b55f881b

📥 Commits

Reviewing files that changed from the base of the PR and between 5f57e0f and 6fa1d69.

📒 Files selected for processing (4)
  • src/js/node/net.ts
  • src/uws_sys/libuwsockets.cpp
  • test/js/node/http/node-http.test.ts
  • test/js/node/net/node-net.test.ts

The onread data handler converted callback throws into a socket 'error'
emit, bypassing the uncaughtException rerouting. Node invokes the onread
callback from onStreamRead without catching, so a throw is fatal.
@robobun

robobun commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the outside-diff finding in 4bffee9: the onread data handler no longer converts callback throws into a socket 'error' emit, so they reach uncaughtException through the wrapper like every other listener (Node's onStreamRead does not catch them either). Added a subprocess test for the onread shape; it fails on an unfixed build (the error listener receives the throw) and passes with this branch.

Comment thread src/js/node/net.ts Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found on re-review — all three earlier inline nits and the CodeRabbit style comments are addressed in the latest commits. Deferring to a human because this wraps every node:net handler-table entry (every TCP socket's dispatch path), changes teardown semantics on listener throw, touches uws_res_end_without_body in the shared uWS layer, and overlaps with #29762 / #32036.

Checked this pass:

  • protectHandler arity (socket, a, b) covers every handler in the three tables — no entry receives >3 args from native dispatch.
  • Wrapping the error handler itself: a throwing user 'error' listener now reaches uncaughtException instead of re-entering the error path — matches Node.
  • The bodyStarted guard still sets HTTP_CONNECTION_CLOSE / HTTP_END_CALLED state flags, so markDone and connection-close accounting are unchanged; only the wire bytes are suppressed.
Extended reasoning...

Overview

Four files: src/js/node/net.ts adds protectHandler/protectHandlers and wraps SocketHandlers, ServerHandlers, SocketHandlers2, and the per-socket onread data handler so exceptions escaping a handler are rethrown on process.nextTick (reaching uncaughtException) and the native socket is terminated. src/uws_sys/libuwsockets.cpp gates the Connection: close header write and terminating CRLF in uws_res_end_without_body on !HTTP_WRITE_CALLED for both SSL and non-SSL branches. Two test files add five subprocess tests for the exception routing and one raw-TCP test for the mid-stream destroy wire bytes.

Security risks

None identified. No auth/crypto/permissions surface. The change routes user-thrown exceptions to a more visible channel (previously silently swallowed with an error listener present), and the uWS change strictly removes bytes that were being incorrectly injected into an already-started body.

Level of scrutiny

High. node:net handler tables are the dispatch boundary for every TCP socket in the Node compat layer — node:http, node:tls, pg, redis clients, etc. all sit on top. Wrapping every handler (including close, error, drain) in a try/catch that terminates the socket on throw is a real semantic change, and the "terminate on any escaping exception" decision — while justified in the description as matching the prior error-routing teardown — is a design call a maintainer should sign off on. uws_res_end_without_body is shared native code also used by Bun.serve, so the guard affects the native server abort path beyond node:http.

Other factors

  • All three of my earlier inline findings are resolved in the current diff (socket?.terminate?.() for the serverName first-arg shape; the http test now destroys once the client has received the chunk frame; the onread inner try/catch is removed with a covering test).
  • The PR explicitly overlaps with two open PRs: #29762 (lifecycle-listener subset of the same wrapping) and #32036 (near-identical uws_res_end_without_body guard plus an additional internalEnd fix). A human should decide sequencing/reconciliation.
  • Test coverage is good: five subprocess fixtures each exit with a distinct code depending on which path the exception took, so misrouting fails loudly; the http test asserts exact wire bytes.
  • CI build #72437 was still building at last timeline update; the PR description notes the relevant test directories pass locally with remaining failures also present on main.

Given the breadth of the code path touched, the design decision on socket teardown, and the overlap with two other open PRs, this is not a candidate for auto-approval.

…ection

ServerHandlers.handshake reported the client-cert verification error
through 'tlsClientError' even when rejectUnauthorized was false and the
connection proceeded. Node only reports tlsClientError when the
connection is torn down; test-tls-sni-option.js asserts this with
mustNotCall, and the assertion was previously swallowed by the error
routing fixed earlier in this branch.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/js/node/net.ts (2)

266-275: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Terminate socketHandle on SNI callback failure. protectHandler() calls terminate() on its first argument, but serverName(server, servername, socketHandle) receives the owning tls.Server there and the accepted connection handle as the third argument. If the callback throws, the handshake stays alive; terminate socketHandle instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/js/node/net.ts` around lines 266 - 275, Update protectHandler to
terminate the actual connection handle on callback failure. Preserve the
existing behavior for callbacks whose first argument is the socket, but when
invoked for serverName with the tls.Server as the first argument, use the third
argument socketHandle for the optional terminate call so the failed handshake is
closed.

271-271: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Capture nextTick once. process.nextTick is still called directly here, so userland can monkey-patch it and block the uncaught-exception rethrow. Use a module-captured primordial-safe alias throughout src/js/node/net.ts.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/js/node/net.ts` at line 271, Update the uncaught-exception rethrow path
around rethrowUncaught to call the module-captured primordial-safe nextTick
alias instead of process.nextTick. Replace direct process.nextTick usage
throughout net.ts with that captured alias, preserving the existing scheduling
and error propagation behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/js/node/net.ts`:
- Around line 266-275: Update protectHandler to terminate the actual connection
handle on callback failure. Preserve the existing behavior for callbacks whose
first argument is the socket, but when invoked for serverName with the
tls.Server as the first argument, use the third argument socketHandle for the
optional terminate call so the failed handshake is closed.
- Line 271: Update the uncaught-exception rethrow path around rethrowUncaught to
call the module-captured primordial-safe nextTick alias instead of
process.nextTick. Replace direct process.nextTick usage throughout net.ts with
that captured alias, preserving the existing scheduling and error propagation
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2f5544a0-a0c9-4a58-81d1-8cf03c0f69ee

📥 Commits

Reviewing files that changed from the base of the PR and between 6fa1d69 and dd852dd.

📒 Files selected for processing (3)
  • src/js/node/net.ts
  • test/js/node/net/node-net.test.ts
  • test/js/node/tls/node-tls-cert.test.ts

@robobun

robobun commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

On the two outside-diff findings:

  • serverName terminate target: declining. A throw can only escape serverName from compat-layer internals, since the user SNICallback call is already wrapped in its own try/catch. When the wrapper catches, it returns undefined, which the native dispatch treats as fall through to the default context, so the handshake proceeds rather than hanging; that matches the pre-PR behavior for this path, and the throw now additionally surfaces as uncaughtException. Special-casing the generic wrapper for the one entry whose first argument is not a socket (the optional call already makes the terminate a no-op there) is not worth the added shape.
  • Capturing process.nextTick: declining. node:net calls process.nextTick directly in 20 existing places, Node's own lib/net.js does the same, and a module-load capture would not be reliable anyway because node:net loads lazily on first require, after user code has had the chance to patch it. Switching the whole file to a captured alias is a standalone change, not part of this fix.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found; all earlier inline feedback has been addressed. Deferring to a human because this changes core Node-compat dispatch semantics across every node:net handler table, alters native uws_res_end_without_body wire behavior, and (in dd852dd) shifts when tlsClientError fires — plus it overlaps with #29762 and #32036.

What was reviewed:

  • protectHandler/protectHandlers wrapping of SocketHandlers/ServerHandlers/SocketHandlers2 and the onread path — genuine socket errors still flow through the error handler unchanged; socket?.terminate?.() is tolerant of the serverName first-arg shape.
  • uws_res_end_without_body bodyStarted guard on both SSL/non-SSL branches — HTTP_CONNECTION_CLOSE state bit is still set even when the header write is skipped; the file-route HEAD path (WROTE_CONTENT_LENGTH without WRITE_CALLED) still gets its CRLF.
  • The tlsClientError emit relocation — checked that admitted-but-unauthorized connections now match Node (no event), and the rejected path still emits before destroy.
  • New subprocess tests — each awaits an observable condition and drains pipes concurrently; the http chunked-destroy test triggers destroy on receipt of the chunk frame rather than a timer.
Extended reasoning...

Overview

This PR spans four concerns: (1) wrapping all three node:net handler tables (SocketHandlers, ServerHandlers, SocketHandlers2) plus the onread data handler in a protectHandler guard that reroutes escaping exceptions to process.nextTick(throw) and then calls socket?.terminate?.(); (2) gating uws_res_end_without_body's Connection: close header and terminating CRLF on !HTTP_WRITE_CALLED so aborting a started chunked response no longer injects header bytes into the body; (3) moving the server-side tlsClientError emit inside the _rejectUnauthorized branch so an unauthorized-but-admitted TLS connection no longer fires it; (4) five new subprocess tests in node-net.test.ts, one raw-TCP test in node-http.test.ts, and a tlsClientError assertion in node-tls-cert.test.ts.

Security risks

None identified. The changes narrow what is written to the wire (fewer bytes on abort) and change where a user-thrown exception surfaces (uncaughtException vs. socket 'error'). No new input parsing, no auth/permission logic. The TLS change only affects which event fires for an already-admitted connection; the reject path is unchanged.

Level of scrutiny

High. src/js/node/net.ts is the Node-compat socket layer that every net/tls/http connection runs through, and protectHandlers wraps every callback in three tables — a broad blast radius where the design choice (catch → nextTick rethrow → terminate()) deserves maintainer sign-off. uws_res_end_without_body is on the response-termination path for Bun.serve and node:http; the guard is small but changes wire bytes. The tlsClientError relocation is a user-observable behavioral change that arrived in the last commit and is only lightly covered in the PR description.

Other factors

  • All prior review feedback (mine and CodeRabbit's) is addressed and resolved; comments are within the 3-line limit.
  • The PR explicitly overlaps with open PRs #29762 (lifecycle-listener subset of the same fix) and #32036 (nearly identical uws_res_end_without_body guard) — a human should decide sequencing.
  • Test coverage is good: each new behavior has a subprocess fixture that would fail on the unfixed build, and the http test asserts exact wire bytes.
  • I did not find bugs in the current revision, but the combination of broad handler-table wrapping, native wire-format change, and a ride-along TLS event semantics change is well outside "simple/mechanical".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

1 participant