Repository navigation
fix(undici): prevent context retention after requests - #9406
Conversation
Overall package sizeSelf size: 8.74 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.4.0 | 127.33 kB | 447.04 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: e92c153 | Docs | View more details | Give us feedback! |
BenchmarksBenchmark execution time: 2026-09-03 19:36:49 Comparing candidate commit e92c153 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 2316 metrics, 12 unstable metrics.
|
0f9df13 to
70c86a7
Compare
70c86a7 to
b83ebdc
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6ffd458e4e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
6ffd458 to
6067da7
Compare
6067da7 to
5da6c72
Compare
5da6c72 to
9acf1d8
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9acf1d87a3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Native diagnostic callbacks entered request spans into the caller's async context. The context outlived finished requests, retained downstream resources, and made later work inherit the wrong span. Keep native diagnostics for normal request lifecycles and instrument only Undici's accepted-upgrade callback, which has no terminal diagnostic event. Activate the request span only while a configured request hook runs. The request-create hot path no longer copies the async store or switches context twice. In two fresh one-million-iteration runs it improved from 43.1-43.5 ns to 10.1-10.2 ns per operation. Refs: nodejs/undici#5761
Released Undici versions omit terminal diagnostics for accepted upgrades, but patched and backported implementations can share those versions. Inspecting the loaded Request method avoids wrapping implementations that already publish terminal trailers.
9acf1d8 to
6b46468
Compare
Accepted upgrade handlers can throw after Undici removes the request from its queue. Affected versions then destroy the socket without a terminal diagnostic event, which retains the span. Publish one fallback error event and rethrow the original error. Scope the hook-context assertion to native diagnostics versions so Node 26 does not format unrelated cyclic span graphs.
* fix(undici): prevent context retention after requests Native diagnostic callbacks entered request spans into the caller's async context. The context outlived finished requests, retained downstream resources, and made later work inherit the wrong span. Keep native diagnostics for normal request lifecycles and instrument only Undici's accepted-upgrade callback, which has no terminal diagnostic event. Activate the request span only while a configured request hook runs. The request-create hot path no longer copies the async store or switches context twice. In two fresh one-million-iteration runs it improved from 43.1-43.5 ns to 10.1-10.2 ns per operation. Refs: nodejs/undici#5761 * fix(undici): gate upgrade fallback by source Released Undici versions omit terminal diagnostics for accepted upgrades, but patched and backported implementations can share those versions. Inspecting the loaded Request method avoids wrapping implementations that already publish terminal trailers. * fix(undici): finish spans after upgrade handler errors Accepted upgrade handlers can throw after Undici removes the request from its queue. Affected versions then destroy the socket without a terminal diagnostic event, which retains the span. Publish one fallback error event and rethrow the original error. Scope the hook-context assertion to native diagnostics versions so Node 26 does not format unrelated cyclic span graphs.
* fix(undici): prevent context retention after requests Native diagnostic callbacks entered request spans into the caller's async context. The context outlived finished requests, retained downstream resources, and made later work inherit the wrong span. Keep native diagnostics for normal request lifecycles and instrument only Undici's accepted-upgrade callback, which has no terminal diagnostic event. Activate the request span only while a configured request hook runs. The request-create hot path no longer copies the async store or switches context twice. In two fresh one-million-iteration runs it improved from 43.1-43.5 ns to 10.1-10.2 ns per operation. Refs: nodejs/undici#5761 * fix(undici): gate upgrade fallback by source Released Undici versions omit terminal diagnostics for accepted upgrades, but patched and backported implementations can share those versions. Inspecting the loaded Request method avoids wrapping implementations that already publish terminal trailers. * fix(undici): finish spans after upgrade handler errors Accepted upgrade handlers can throw after Undici removes the request from its queue. Affected versions then destroy the socket without a terminal diagnostic event, which retains the span. Publish one fallback error event and rethrow the original error. Scope the hook-context assertion to native diagnostics versions so Node 26 does not format unrelated cyclic span graphs.
* fix(undici): prevent context retention after requests Native diagnostic callbacks entered request spans into the caller's async context. The context outlived finished requests, retained downstream resources, and made later work inherit the wrong span. Keep native diagnostics for normal request lifecycles and instrument only Undici's accepted-upgrade callback, which has no terminal diagnostic event. Activate the request span only while a configured request hook runs. The request-create hot path no longer copies the async store or switches context twice. In two fresh one-million-iteration runs it improved from 43.1-43.5 ns to 10.1-10.2 ns per operation. Refs: nodejs/undici#5761 * fix(undici): gate upgrade fallback by source Released Undici versions omit terminal diagnostics for accepted upgrades, but patched and backported implementations can share those versions. Inspecting the loaded Request method avoids wrapping implementations that already publish terminal trailers. * fix(undici): finish spans after upgrade handler errors Accepted upgrade handlers can throw after Undici removes the request from its queue. Affected versions then destroy the socket without a terminal diagnostic event, which retains the span. Publish one fallback error event and rethrow the original error. Scope the hook-context assertion to native diagnostics versions so Node 26 does not format unrelated cyclic span graphs.
* fix(undici): prevent context retention after requests Native diagnostic callbacks entered request spans into the caller's async context. The context outlived finished requests, retained downstream resources, and made later work inherit the wrong span. Keep native diagnostics for normal request lifecycles and instrument only Undici's accepted-upgrade callback, which has no terminal diagnostic event. Activate the request span only while a configured request hook runs. The request-create hot path no longer copies the async store or switches context twice. In two fresh one-million-iteration runs it improved from 43.1-43.5 ns to 10.1-10.2 ns per operation. Refs: nodejs/undici#5761 * fix(undici): gate upgrade fallback by source Released Undici versions omit terminal diagnostics for accepted upgrades, but patched and backported implementations can share those versions. Inspecting the loaded Request method avoids wrapping implementations that already publish terminal trailers. * fix(undici): finish spans after upgrade handler errors Accepted upgrade handlers can throw after Undici removes the request from its queue. Affected versions then destroy the socket without a terminal diagnostic event, which retains the span. Publish one fallback error event and rethrow the original error. Scope the hook-context assertion to native diagnostics versions so Node 26 does not format unrelated cyclic span graphs.
Summary
Native Undici diagnostic callbacks entered request spans into the caller's async context. The context outlived finished requests, retained downstream resources, and made later work inherit the wrong span.
Keep native diagnostics for normal request lifecycles. For accepted upgrades, inspect the loaded Request method and install the fallback only when that method does not publish terminal diagnostics. Patched and backported Undici implementations remain untouched.
Activate the request span only while a configured request hook runs.
The request-create hot path no longer copies the async store or switches context twice. Two fresh one-million-iteration runs improved from 43.1-43.5 ns to 10.1-10.2 ns per operation.
The native Undici fix is tracked in nodejs/undici#5761.