René's URL Explorer Experiment


Title: `readable.find()`/`some()`/`every()` don't destroy the stream on match when the source hasn't ended · Issue #64261 · nodejs/node · GitHub

Open Graph Title: `readable.find()`/`some()`/`every()` don't destroy the stream on match when the source hasn't ended · Issue #64261 · nodejs/node

X Title: `readable.find()`/`some()`/`every()` don't destroy the stream on match when the source hasn't ended · Issue #64261 · nodejs/node

Description: Version v24.18.0 (reproduces on this version; likely affects any version with the stream iterator helpers, i.e. Readable.find/some/every) Platform Linux (reproduces regardless of platform - pure JS logic issue) Subsystem No response What...

Open Graph Description: Version v24.18.0 (reproduces on this version; likely affects any version with the stream iterator helpers, i.e. Readable.find/some/every) Platform Linux (reproduces regardless of platform - pure JS...

X Description: Version v24.18.0 (reproduces on this version; likely affects any version with the stream iterator helpers, i.e. Readable.find/some/every) Platform Linux (reproduces regardless of platform - pure JS...

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

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"`readable.find()`/`some()`/`every()` don't destroy the stream on match when the source hasn't ended","articleBody":"### Version\n\nv24.18.0 (reproduces on this version; likely affects any version with the stream iterator helpers, i.e. Readable.find/some/every)\n\n### Platform\n\nLinux (reproduces regardless of platform - pure JS logic issue)\n\n### Subsystem\n\n_No response_\n\n### What steps will reproduce the bug?\n\n```js\nimport { PassThrough } from \"node:stream\";\n\nconst pt = new PassThrough();\n\nconst matchPromise = pt.find((chunk) => chunk.toString().includes(\"MATCH\"));\n\npt.write(\"first line\\n\");\npt.write(\"MATCH this one\\n\");\n\nconst result = await matchPromise;\nconsole.log(\"find() resolved with:\", JSON.stringify(result.toString()));\nconsole.log(\"pt.destroyed immediately after resolution:\", pt.destroyed);\n\nawait new Promise((r) => setTimeout(r, 100));\nconsole.log(\"pt.destroyed 100ms later:\", pt.destroyed);\n```\n\n### How often does it reproduce? Is there a required condition?\n\n100% reproducible. Condition: the source stream must still be open (not `.end()`-ed) and must not receive another chunk immediately after the matching one. This is the common case for any long-lived/never-ending stream (e.g. tailing a child process's stdout/stderr, or any other indefinite source) - which is exactly the kind of stream `.find()`/`.some()`/`.every()` are attractive for using with (`for await`-based line/event scanning).\n\n### What is the expected behavior? Why is that the expected behavior?\n\nPer the documentation for [`readable.find(fn[, options])`](https://nodejs.org/api/stream.html#readablefindfn-options) (identical wording for `.some()` / `.every()`):\n\n> Once an `fn` call's awaited return value is truthy, **the stream is destroyed** and the promise is fulfilled with value for which `fn` returned a truthy value.\n\nSo `pt.destroyed` should become `true` once `find()`'s promise resolves (or shortly after, since `.destroy()` is not fully synchronous).\n\n### What do you see instead?\n\n```\nfind() resolved with: \"first line\\nMATCH this one\\n\"\npt.destroyed immediately after resolution: false\npt.destroyed 100ms later: false\n```\n\n`pt` is never destroyed, no matter how long you wait, as long as nothing else writes another chunk to it (in this repro, it's just never destroyed at all, period, since nothing writes again).\n\n### Additional information\n\nThe root cause, traced in `lib/internal/streams/operators.js`:\n\n`find` is a thin wrapper around `filter`, which is a thin wrapper around `map`:\n\n```js\nasync function find(fn, options) {\n  for await (const result of filter.call(this, fn, options)) {\n    return result;\n  }\n  return undefined;\n}\n```\n\nThe `return result` triggers the implicit `.return()` call on the `filter`/`map` async generator (standard `for await...of` early-exit semantics) - this correctly unwinds the OUTER generator's own `finally` block (setting `done = true` and resolving pending `resume`/`next` promises inside `map`).\n\nHowever, `map`'s implementation spawns a *separate, fire-and-forget* `pump()` async function that independently iterates the original source stream:\n\n```js\nasync function pump() {\n  try {\n    for await (let val of stream) {   // \u003c-- this is a DIFFERENT for-await-of loop, over the original source\n      if (done) {\n        return;\n      }\n      ...\n```\n\n`pump()`'s `for await (let val of stream)` is a *different* iterator/loop than the one `find()`'s `for await` unwinds. Setting `done = true` from the outer generator's cleanup does not itself unblock this inner loop - it's only checked *after* `stream`'s iterator yields a new value. If the source never produces another chunk after the matching one (because it's still open and simply idle), `pump()` stays permanently suspended awaiting the next chunk from `stream`, and nothing ever calls `.destroy()` (or `.return()`) on `stream` itself.\n\nThere is no explicit `stream.destroy()` call anywhere in `map`/`filter`/`find`'s implementation in `lib/internal/streams/operators.js` - the \"stream is destroyed\" behavior described in the docs appears to rely entirely on the source stream separately reaching natural end/auto-destroy on its own, which only coincidentally happens to align with \"matched\" for finite/short-lived sources, not because `find`/`some`/`every` themselves ever destroy it.\n\n(I confirmed this distinction experimentally: a finite `Readable.from([...])` source does eventually show `destroyed: true` after a match, but that's because the array-backed stream naturally runs to completion regardless of the match and gets auto-destroyed via `autoDestroy` once it truly ends - not because `find()` destroyed it. A still-open, indefinite source like the `PassThrough` above never gets destroyed at all.)\n\nAnyone relying on the documented \"the stream is destroyed\" behavior to avoid manually cleaning up resources after `find()`/`some()`/`every()` on a long-lived stream (e.g. scanning a child process's stdout for a marker line) will leak that stream indefinitely - it stays alive, un-destroyed, holding onto internal buffers/decoders, until whatever holds a reference to it is garbage collected, with no explicit teardown ever occurring.","author":{"url":"https://github.com/perrin4869","@type":"Person","name":"perrin4869"},"datePublished":"2026-07-02T15:33:54Z","url":"https://github.com/nodejs/node/issues/64261"}

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:26bc448e-52b3-de8e-57c4-19fec14ac69f
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-id83AA:20B00F:1E4BE1:29800A:6AED4364
html-safe-noncecf77dc41dc3a32fc4678731f0359c130e69533acda9febf8345ef2bba742a1ff
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4M0FBOjIwQjAwRjoxRTRCRTE6Mjk4MDBBOjZBRUQ0MzY0IiwidmlzaXRvcl9pZCI6IjUxODg1NzI1MTk3NDc4OTYxNjQiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmac5b2a7315ac874ca1939644b53d5dd05d743e2d06fa2a278cef321d64392416e4
hovercard-subject-tagissue:4795927556
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/64261/issue_layout
twitter:imagehttps://opengraph.githubassets.com/5156e4a7664156e792eedd616e65ad6255a84700ab4fac762d28e066d40df338/nodejs/node/issues/64261
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/5156e4a7664156e792eedd616e65ad6255a84700ab4fac762d28e066d40df338/nodejs/node/issues/64261
og:image:altVersion v24.18.0 (reproduces on this version; likely affects any version with the stream iterator helpers, i.e. Readable.find/some/every) Platform Linux (reproduces regardless of platform - pure JS...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernameperrin4869
hostnamegithub.com
expected-hostnamegithub.com
None56fb42677ae87ed3e64410323d67980aa65d0485568a7858f874e7edfc6d1c11
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
release9c9a37e2423ed382cf39f70b5aa4b4858b40a3b0
ui-targetfull
theme-color#1e2327
color-schemelight dark
react-app-nameissues

Links:

Skip to contenthttps://github.com/nodejs/node/issues/64261#start-of-content
https://github.com/
Sign inhttps://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fnodejs%2Fnode%2Fissues%2F64261
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%2F64261
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/64261
Reloadhttps://github.com/nodejs/node/issues/64261
Reloadhttps://github.com/nodejs/node/issues/64261
nodejshttps://github.com/nodejs
nodehttps://github.com/nodejs/node
Codehttps://github.com/nodejs/node
Issues655 (655)https://github.com/nodejs/node/issues
Pull requests664 (664)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/64261
New issuehttps://github.com/login?return_to=https://github.com/nodejs/node/issues/64261
#64264https://github.com/nodejs/node/pull/64264
readable.find()/some()/every() don't destroy the stream on match when the source hasn't endedhttps://github.com/nodejs/node/issues/64261#top
#64264https://github.com/nodejs/node/pull/64264
streamIssues and PRs related to Node.js streams.https://github.com/nodejs/node/issues?q=state%3Aopen%20label%3A%22stream%22
https://github.com/perrin4869
perrin4869https://github.com/perrin4869
on Jul 2, 2026https://github.com/nodejs/node/issues/64261#issue-4795927556
readable.find(fn[, options])https://nodejs.org/api/stream.html#readablefindfn-options
Renegade334https://github.com/Renegade334
streamIssues and PRs related to Node.js streams.https://github.com/nodejs/node/issues?q=state%3Aopen%20label%3A%22stream%22
on Jul 2, 2026https://github.com/nodejs/node/issues/64261#event-27491723354
Y1D7NGhttps://github.com/Y1D7NG
on Sep 6, 2026https://github.com/nodejs/node/issues/64261#event-30645386957
stream: destroy source when map iterator closes earlyhttps://github.com/Y1D7NG/node/commit/457b5cb8daf03162dfd95f276b5a3c042d1e3643
457b5cbhttps://github.com/Y1D7NG/node/commit/457b5cb8daf03162dfd95f276b5a3c042d1e3643
stream: destroy source when map iterator closes earlyhttps://github.com/Y1D7NG/node/commit/a28f607a0943bb0e7a3abab32d77998e6bd379fe
a28f607https://github.com/Y1D7NG/node/commit/a28f607a0943bb0e7a3abab32d77998e6bd379fe
nodejs-github-bothttps://github.com/nodejs-github-bot
on Sep 7, 2026https://github.com/nodejs/node/issues/64261#event-30691185652
stream: destroy source when map iterator closes earlyhttps://github.com/nodejs/node/commit/9f7ae86d8b57e16ec0384af0be29fb6a768c2ab7
9f7ae86https://github.com/nodejs/node/commit/9f7ae86d8b57e16ec0384af0be29fb6a768c2ab7
nodejs-github-bothttps://github.com/nodejs-github-bot
completedhttps://github.com/nodejs/node/issues?q=is%3Aissue%20state%3Aclosed%20archived%3Afalse%20reason%3Acompleted
#64264https://github.com/nodejs/node/pull/64264
on Sep 7, 2026https://github.com/nodejs/node/issues/64261#event-30691185816
Sign up for freehttps://github.com/signup?return_to=https://github.com/nodejs/node/issues/64261
Sign in to commenthttps://github.com/login?return_to=https://github.com/nodejs/node/issues/64261
streamIssues and PRs related to Node.js streams.https://github.com/nodejs/node/issues?q=state%3Aopen%20label%3A%22stream%22
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.