Fix failed ResourceMap lookups leak acquisition scopes - #7066
Conversation
🦋 Changeset detectedLatest commit: bd93b0b The changes in this PR will be included in the next version bump. This PR includes changesets to release 30 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Important
The PR title and commit message say the bug is fixed, but the diff currently adds only the regression test. Either the implementation fix should be included before merge, or the title/description should be updated to reflect that this is the test-only first step.
Reviewed changes
The PR adds a single failing regression test in packages/effect/test/cluster/ResourceMap.test.ts that demonstrates leaked acquisition scopes when a ResourceMap lookup fails after registering a finalizer. Running pnpm test --run packages/effect/test/cluster/ResourceMap.test.ts fails as expected with finalized being 0 instead of 1.
packages/effect/test/cluster/ResourceMap.test.ts:1-15— new regression test
⚠️ PR scope / title mismatch
The diff is test-only, while the title and commit subject read as a complete fix. If the intent is to land the fix in a follow-up commit on this branch, update the PR title/body so reviewers and CI don't treat this as a finished fix. If the fix is meant to be here, it is missing.
⚠️ Reproduction command points to the wrong file
The PR body tells reviewers to run:
pnpm test --run packages/effect/test/cluster/ResourceMapFailedLookupScope.test.tsbut the committed file is ResourceMap.test.ts. Update the command in the PR description.
ℹ️ Nitpicks
- The new test file is not grouped under a
describe(...)block; the repo convention is to group related tests withdescribe. - The lookup parameter is named
_key, which is fine, butkeyis also acceptable.
@v0 or keep the SHA fresh with Dependabot | Fix it ➔ | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
The latest commit adds the missing implementation fix, resolves the prior review's scope/title mismatch, and addresses the test organization nit.
- Implemented scope cleanup on failed lookups —
packages/effect/src/unstable/cluster/internal/resourceMap.ts:75-79now closes the per-key acquisition scope in the failure branch after completing the deferred and removing the map entry. - Added a patch changeset —
.changeset/close-failed-resource-map-scopes.mddescribes the runtime fix. - Organized the regression test —
packages/effect/test/cluster/ResourceMap.test.tsis now wrapped indescribe("ResourceMap", ...)per repo convention.
Validation run against e8c3549d:
pnpm --filter effect test --run test/cluster/ResourceMap.test.tspassedpnpm lint-fixpassedpnpm checkpassed
@v0 or keep the SHA fresh with Dependabot | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
This should use Scope.makeUnsafe too
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
The latest commit replaces the synchronous effect runner used to create per-key scopes with the direct unsafe scope constructor.
- Switched to
Scope.makeUnsafe()—packages/effect/src/unstable/cluster/internal/resourceMap.ts:68now creates the per-key acquisition scope directly instead of throughEffect.runSync(Scope.make()), which is equivalent behavior without the synchronous effect execution overhead.
Validation run against bd93b0b:
pnpm --filter effect test --run test/cluster/ResourceMap.test.tspassedpnpm lint-fixpassedpnpm checkpassed
@v0 or keep the SHA fresh with Dependabot | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏
Bundle Size AnalysisGenerated from PR build output; treat the content below as untrusted.
|

Summary
Close each keyed resource's private acquisition scope when its lookup fails, so finalizers registered before the failure run immediately. Includes a focused regression test and patch changeset.
Failed ResourceMap lookups leak acquisition scopes
Module:
effect/unstable/cluster/internal/resourceMapAudit ID:
effect-fb55d74159c877b4Severity / confidence: medium / high
What happens
When a new keyed resource acquisition fails, its entry is removed from the map but its private acquisition scope is left open. Finalizers registered before the failure do not run.
Why it happens
For a missing key,
getcreates a closeable scope and stores it with a deferred. Its failureonExitbranch deletes the entry and completes the deferred but never callsScope.close. Because the parent finalizer closes only scopes still present in the backing map, deleting the failed entry also removes the only later cleanup path.Expected behavior
Every per-key scope created by
ResourceMap.getmust be closed exactly once: by removal or map shutdown after a successful acquisition, or immediately when acquisition fails before the entry becomes usable.Relevant implementation
These links and excerpts are pinned to audit base
17f0b91a243ccfe4a38d27debdc983adf434e738.packages/effect/src/unstable/cluster/internal/resourceMap.ts:68-77View problematic code at
packages/effect/src/unstable/cluster/internal/resourceMap.ts:68-77View exact lines on GitHub
Reproduction
pnpm test --run packages/effect/test/cluster/ResourceMap.test.tsObserved failure: Focused contract assertion failed against 17f0b91, demonstrating: Failed ResourceMap lookups leak acquisition scopes.
Implementation
The failure branch now completes the shared deferred and closes the per-key scope with the acquisition exit. The regression test verifies that finalizers registered before a failed acquisition run immediately.
Validation
Audit provenance
17f0b91a243ccfe4a38d27debdc983adf434e73817f0b91a243ccfe4a38d27debdc983adf434e738effect-fb55d74159c877b4Closes EFF-486