René's URL Explorer Experiment


Title: TransformStream error during pipeTo crashes the process despite being caught (v26.4.0 regression) · Issue #64561 · nodejs/node · GitHub

Open Graph Title: TransformStream error during pipeTo crashes the process despite being caught (v26.4.0 regression) · Issue #64561 · nodejs/node

X Title: TransformStream error during pipeTo crashes the process despite being caught (v26.4.0 regression) · Issue #64561 · nodejs/node

Description: Version v26.4.0, v26.5.0, v27.0.0-nightly202607157a11a9b2db Platform Darwin 25.5.0 arm64 (pure JS internals — unlikely to be platform-specific) Subsystem webstreams What steps will reproduce the bug? When a TransformStream in a pipeThrou...

Open Graph Description: Version v26.4.0, v26.5.0, v27.0.0-nightly202607157a11a9b2db Platform Darwin 25.5.0 arm64 (pure JS internals — unlikely to be platform-specific) Subsystem webstreams What steps will reproduce the bu...

X Description: Version v26.4.0, v26.5.0, v27.0.0-nightly202607157a11a9b2db Platform Darwin 25.5.0 arm64 (pure JS internals — unlikely to be platform-specific) Subsystem webstreams What steps will reproduce the bu...

Opengraph URL: https://github.com/nodejs/node/issues/64561

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"TransformStream error during pipeTo crashes the process despite being caught (v26.4.0 regression)","articleBody":"### Version\n\nv26.4.0, v26.5.0, v27.0.0-nightly202607157a11a9b2db\n\n### Platform\n\n```text\nDarwin 25.5.0 arm64 (pure JS internals — unlikely to be platform-specific)\n```\n\n### Subsystem\n\nwebstreams\n\n### What steps will reproduce the bug?\n\nWhen a `TransformStream` in a `pipeThrough()` chain throws while an upstream chunk is still in flight, the process crashes with an uncaught exception — even though the `pipeTo()` promise rejects as expected and user code catches the error.\n\n```js\n// repro.mjs\nconst source = new ReadableStream({\n\tstart(controller) {\n\t\tcontroller.enqueue(\"a\");\n\t\tcontroller.enqueue(\"b\");\n\t\tcontroller.close();\n\t}\n});\n\nconst asyncPassThrough = new TransformStream({\n\tasync transform(chunk, controller) {\n\t\tcontroller.enqueue(chunk);\n\t}\n});\n\nconst identity = new TransformStream();\n\nconst failingTransform = new TransformStream({\n\ttransform() {\n\t\tthrow new Error(\"boom\");\n\t}\n});\n\ntry {\n\tawait source\n\t\t.pipeThrough(asyncPassThrough)\n\t\t.pipeThrough(identity)\n\t\t.pipeThrough(failingTransform)\n\t\t.pipeTo(new WritableStream());\n} catch (error) {\n\tconsole.log(\"caught: \" + error.message);\n}\n```\n\nExecute with: `node repro.mjs`\n\nThe shape is timing-sensitive: the second chunk must reach the failing stream *after* it has errored. At least two chunks are required, and removing either intermediate stage (or making `asyncPassThrough`'s `transform` synchronous) changes the interleaving enough that the crash disappears.\n\n### How often does it reproduce? Is there a required condition?\n\nDeterministic with the reproduction above.\n\nBehavior across runtimes and versions:\n\n| Runtime | Result |\n| --- | --- |\n| Node.js v24.13.0, v25.9.0, v26.0.0, v26.2.0, v26.3.1 | `caught: boom`, exit 0 |\n| Node.js v26.4.0, v26.5.0, v27 nightly | `caught: boom`, then **uncaught exception, exit 1** |\n| Deno 2.9.3, Bun 1.3.14 | `caught: boom`, exit 0 |\n\n### What is the expected behavior? Why is that the expected behavior?\n\nThe error thrown by the transform should surface exactly once, as the rejection of the `pipeTo()` promise. Since that rejection is caught, the process should exit cleanly. This is the behavior of Node.js ≤ v26.3.1, Deno, Bun, and browsers.\n\n### What do you see instead?\n\nThe rejection is delivered and caught (`caught: boom` is printed), and then the process crashes anyway with a duplicate of the same error:\n\n```text\ncaught: boom\nnode:internal/process/promises:324\n    triggerUncaughtException(err, true /* fromPromise */);\n    ^\n\nError: boom\n    at Object.transform (file:///…/repro.mjs:19:9)\n    at node:internal/webstreams/util:195:32\n    at transformStreamDefaultControllerPerformTransform (node:internal/webstreams/transformstream:531:18)\n    at transformStreamDefaultSinkWriteAlgorithm (node:internal/webstreams/transformstream:577:10)\n    at node:internal/webstreams/transformstream:367:16\n    at writableStreamDefaultControllerProcessWrite (node:internal/webstreams/writablestream:1138:5)\n    at writableStreamDefaultControllerAdvanceQueueIfNeeded (node:internal/webstreams/writablestream:1245:5)\n    at writableStreamDefaultControllerWrite (node:internal/webstreams/writablestream:1100:3)\n    at writableStreamDefaultWriterWrite (node:internal/webstreams/writablestream:991:3)\n    at node:internal/webstreams/readablestream:1733:33\n\nNode.js v26.5.0\n```\n\n### Additional information\n\n**Root cause.** Bisecting releases points to v26.4.0, and specifically to 6af90267de (#63572, \"stream: drop per-chunk Promise alloc in pipeTo\"), which changed both pipeTo write sites from `setPromiseHandled(state.currentWrite)` — which attaches real reaction handlers — to the native `markPromiseAsHandled(state.currentWrite)` binding, which only sets the promise's `[[PromiseIsHandled]]` bit:\n\n```js\n// lib/internal/webstreams/readablestream.js (PipeToReadableStreamReadRequest[kChunk])\nqueueMicrotask(() => {\n  this.state.currentWrite = writableStreamDefaultWriterWrite(this.writer, chunk);\n  markPromiseAsHandled(this.state.currentWrite);\n  this.promise.resolve(false);\n});\n```\n\nWhen the chunk arrives after the destination has already errored, `writableStreamDefaultWriterWrite` takes an early-return path and returns `PromiseReject(storedError)` — a promise that is **already rejected at creation**. V8 enqueues the `kPromiseRejectWithNoHandler` notification at rejection time. Setting the handled bit afterwards does not emit a `kPromiseHandlerAddedAfterReject` event (no handler is actually attached), so nothing cancels the pending notification, and Node promotes it to an uncaught exception at the end of the tick. The previous `setPromiseHandled` attached a real `.then` reaction, which does emit the cancellation event, so marking \"too late\" was harmless.\n\nThe ordering dependency is easy to demonstrate with the binding directly:\n\n```console\n$ node --expose-internals -e \"\nconst { internalBinding } = require('internal/test/binding');\nconst { markPromiseAsHandled } = internalBinding('util');\nconst p = Promise.reject(new Error('rejected, then marked'));\nmarkPromiseAsHandled(p);\n\"   # crashes\n\n$ node --expose-internals -e \"\nconst { internalBinding } = require('internal/test/binding');\nconst { markPromiseAsHandled } = internalBinding('util');\nconst { promise, reject } = Promise.withResolvers();\nmarkPromiseAsHandled(promise);\nreject(new Error('marked, then rejected'));\n\"   # exits cleanly\n```\n\nBoth call sites changed by #63572 have the same exposure (the batched fast-path write in `readableStreamPipeTo` and the `PipeToReadableStreamReadRequest[kChunk]` slow path; the reproduction above hits the slow path). A fix could restore real handlers at these two sites, or keep the optimization for the common pending-promise case and fall back to attaching a handler when the returned write promise is already rejected.\n\n**Impact.** Found via zip.js, where reading a ZipCrypto-encrypted entry with a wrong password now kills the whole process: the `Invalid password` error thrown inside a decryption `TransformStream` crashes Node even though the library's `pipeTo` rejection handling and the application's `try`/`catch` both work as intended. Any `pipeThrough` chain whose transform can throw mid-stream (validation, decryption, parsing) is affected, and there is no userland workaround short of a process-level `unhandledRejection` handler.\n","author":{"url":"https://github.com/gildas-lormeau","@type":"Person","name":"gildas-lormeau"},"datePublished":"2026-07-17T16:21:23Z","url":"https://github.com/nodejs/node/issues/64561"}

react-profiling0
react-import-mapreact,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf
route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:14c7e115-40ba-6872-5a6a-440a8acc544c
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-idDC08:2C47BC:449246:596183:6AED237E
html-safe-nonce57ebef739b0a2b5843a2512ff29473b0efabf2586a7c026c7fe827f3d6e7df85
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJEQzA4OjJDNDdCQzo0NDkyNDY6NTk2MTgzOjZBRUQyMzdFIiwidmlzaXRvcl9pZCI6IjM2MzE4MzAxNjI2NzcyNDQ3OTgiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmaca0dd673508a1490debf931a8aba13abc0ae4bbe669d945a6b12daa7786f68d9f
hovercard-subject-tagissue:4913024490
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/nodejs/node/64561/issue_layout
twitter:imagehttps://opengraph.githubassets.com/34b15da3c8fc7b8db2d0ed45c3efc86fd0d9fe80135188df254f0c56492aff91/nodejs/node/issues/64561
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/34b15da3c8fc7b8db2d0ed45c3efc86fd0d9fe80135188df254f0c56492aff91/nodejs/node/issues/64561
og:image:altVersion v26.4.0, v26.5.0, v27.0.0-nightly202607157a11a9b2db Platform Darwin 25.5.0 arm64 (pure JS internals — unlikely to be platform-specific) Subsystem webstreams What steps will reproduce the bu...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernamegildas-lormeau
hostnamegithub.com
expected-hostnamegithub.com
Nonee3e0f7f63e50c6fe879198a93a0a023a648ecc0a5e9bc3b5e033ac57172237e6
turbo-cache-controlno-preview
go-importgithub.com/nodejs/node git https://github.com/nodejs/node.git
octolytics-dimension-user_id9950313
octolytics-dimension-user_loginnodejs
octolytics-dimension-repository_id27193779
octolytics-dimension-repository_nwonodejs/node
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id27193779
octolytics-dimension-repository_network_root_nwonodejs/node
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release707a24b346ac8a82878b9c084efaa38a997660cb
ui-targetcanary-2
theme-color#1e2327
color-schemelight dark
react-app-nameissues

Links:

Skip to contenthttps://github.com/nodejs/node/issues/64561#start-of-content
https://github.com/
Sign inhttps://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fnodejs%2Fnode%2Fissues%2F64561
GitHubRepository hosting, code review, and collaborationhttps://github.com/platform
CopilotAI coding agent for tasks, projects, and automated workhttps://github.com/features/copilot
ActionsCI/CD and automationhttps://github.com/features/actions
Code QualityQuality analysis, fixes, and enforcementhttps://github.com/features/code-quality
CodespacesCloud development environmentshttps://github.com/features/codespaces
Code SecurityVulnerability detection and remediationhttps://github.com/security/advanced-security/code-security
Secret ProtectionSecret scanning and leak preventionhttps://github.com/security/advanced-security/secret-protection
All Featureshttps://github.com/features
Documentationhttps://docs.github.com/en
Traininghttps://learn.github.com/skills
Certificationshttps://learn.github.com/credentials
Build with Copilothttps://github.com/features/ai
Customize Copilothttps://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/customize-copilot-overview
Integrationshttps://github.com/marketplace
Trending reposhttps://github.com/trending
GitHub Sponsorshttps://github.com/open-source/sponsors
Developer articleshttps://github.com/resources/articles
ChangelogYour source for the latest features, improvements, and fixes across GitHub products, all in one place.https://github.blog/changelog/
Enterpriseshttps://github.com/enterprise
Teamhttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
See all industrieshttps://github.com/solutions/industry
Why GitHubhttps://github.com/why-github
Customer Storieshttps://github.com/customer-stories
Business insightshttps://github.com/solutions/executive-insights
Trust Centerhttps://github.com/trust-center
GitHub Advanced SecurityEnterprise-grade code securityhttps://github.com/security/advanced-security
Copilot for businessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Documentationhttps://docs.github.com/en
Resource centerhttps://github.com/resources
Bloghttps://github.blog/
Events & webinarshttps://github.com/resources/events
Community Forumhttps://github.com/orgs/community/discussions
Customer Storieshttps://github.com/customer-stories
Integrationshttps://github.com/marketplace
Customer supporthttps://help.github.com/
Traininghttps://learn.github.com/skills
GitHub Statushttps://www.githubstatus.com/
Abouthttps://github.com/about
Partnershttps://github.com/partners
Changeloghttps://github.blog/changelog/
GitHub UniverseThe event for developers, by developers — talks, workshops, and what’s next for GitHub.https://githubuniverse.com/
Pricinghttps://github.com/pricing
Sign inhttps://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fnodejs%2Fnode%2Fissues%2F64561
Sign uphttps://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=nodejs%2Fnode
Reloadhttps://github.com/nodejs/node/issues/64561
Reloadhttps://github.com/nodejs/node/issues/64561
Reloadhttps://github.com/nodejs/node/issues/64561
nodejshttps://github.com/nodejs
nodehttps://github.com/nodejs/node
Codehttps://github.com/nodejs/node
Issues657 (657)https://github.com/nodejs/node/issues
Pull requests666 (666)https://github.com/nodejs/node/pulls
Actionshttps://github.com/nodejs/node/actions
Projectshttps://github.com/nodejs/node/projects
Security and qualityhttps://github.com/nodejs/node/security
Insightshttps://github.com/nodejs/node/pulse
https://github.com/nodejs/node
New issuehttps://github.com/login?return_to=https://github.com/nodejs/node/issues/64561
New issuehttps://github.com/login?return_to=https://github.com/nodejs/node/issues/64561
TransformStream error during pipeTo crashes the process despite being caught (v26.4.0 regression)https://github.com/nodejs/node/issues/64561#top
https://github.com/gildas-lormeau
gildas-lormeauhttps://github.com/gildas-lormeau
on Jul 17, 2026https://github.com/nodejs/node/issues/64561#issue-4913024490
6af9026https://github.com/nodejs/node/commit/6af90267de37798713cd097836c1a89f3ec311bf
#63572https://github.com/nodejs/node/pull/63572
#63572https://github.com/nodejs/node/pull/63572
https://github.com/apps/github-actions
github-actionshttps://github.com/apps/github-actions
on Oct 16, 2026https://github.com/nodejs/node/issues/64561#issuecomment-6205872534
GitHub Actionshttps://help.github.com/en/actions
github-actionshttps://github.com/apps/github-actions
staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.https://github.com/nodejs/node/issues?q=state%3Aopen%20label%3A%22stale%22
on Oct 16, 2026https://github.com/nodejs/node/issues/64561#event-33396070194
https://github.com/gildas-lormeau
gildas-lormeauhttps://github.com/gildas-lormeau
on Oct 16, 2026https://github.com/nodejs/node/issues/64561#issuecomment-6212124733
#64890https://github.com/nodejs/node/pull/64890
github-actionshttps://github.com/apps/github-actions
staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.https://github.com/nodejs/node/issues?q=state%3Aopen%20label%3A%22stale%22
on Oct 17, 2026https://github.com/nodejs/node/issues/64561#event-33496098091
Sign up for freehttps://github.com/signup?return_to=https://github.com/nodejs/node/issues/64561
Sign in to commenthttps://github.com/login?return_to=https://github.com/nodejs/node/issues/64561
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.