fix(core): guard Deferred waiter cleanup in vendored effect patch - #41858
Merged
Conversation
Completion (doneUnsafe) resumes every waiter then sets resumes to undefined. A waiter's interrupt cleanup running after completion dereferenced the cleared array: TypeError: undefined is not an object (evaluating 'X.resumes.indexOf') Observed in production as HTTP 500s on GET /api/session/:id/question (request abort interrupting the long-poll's awaiting fiber racing a concurrent completion). The bug is unfixed upstream at 4.0.0-beta.107; an upstream PR is in flight, but this patch protects releases now. Also repairs the existing SSE-identifier hunk for src/unstable/httpapi/ HttpApiSchema.ts: its line offsets were wrong (407 vs 430), so bun fuzz-applied it mid-overload-signature, leaving syntactically broken TypeScript in the vendored src file (latent - only dist executes). Regenerated via bun patch from pristine + intended edits; dist output is byte-identical to before for the SSE change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Extends
patches/effect@4.0.0-beta.101.patchwith a defensive guard inDeferred's_awaitcleanup, fixing a production crash:The race
Deferred._awaitregisters a waiter and returns a cleanup that unregisters it viaself.resumes!.indexOf(resume). Completion (doneUnsafe) resumes every waiter and then setsself.resumes = undefined. When a waiter's interrupt cleanup runs after completion — observed onGET /api/session/:id/questionlong-polls where a request abort interrupts the awaiting fiber while a concurrent completion lands — the cleanup dereferencesundefinedand the request 500s.The invariant argument: a cleanup closure only exists if the deferred was pending at registration (
resumeswas an array), and the only line in the module that ever makesresumesundefined again is completion. The production TypeError is therefore proof that the complete-then-cleanup order is reachable.Fix
Applied to both
dist/Deferred.js(what runs) andsrc/Deferred.ts(shipped alongside). The bug is unfixed upstream at4.0.0-beta.107head; an upstream fix PR is in flight, but this patch stops the 500s at the next opencode release instead of waiting on an effect release + version bump.Drive-by repair
While regenerating the patch with
bun patch, discovered the existing SSE-identifier hunk forsrc/unstable/httpapi/HttpApiSchema.tshad wrong line offsets (407 vs the real 430), so bun had been fuzz-applying it mid-overload-signature — leaving syntactically broken TypeScript in the vendored src file. Latent (onlydistexecutes), but this PR regenerates that hunk correctly from pristine + the intended edits. Thedistoutput for the SSE change is unchanged.Testing
bun install --force: patch applies cleanly; resolvedeffect/Deferredmodule contains the guard.src/unstable/httpapi/HttpApiSchema.tsis now valid TypeScript with the SSE change at the intended location.