fix(functions): clean up cross-signal abort listener on invoke() return#2487
Merged
kallebysantos merged 1 commit intoJul 20, 2026
Merged
Conversation
When invoke() is called with both timeout and signal, an event listener is added to the caller's AbortSignal to propagate abort to the internal timeoutController. Previously that listener was never removed, leaving a stale reference to the timeoutController alive for the lifetime of the signal. Now the listener is stored in onAbort and removed in the finally block, so callers that reuse the same AbortController across multiple invocations do not accumulate dangling listeners.
kallebysantos
approved these changes
Jul 20, 2026
@supabase/auth-js
@supabase/functions-js
@supabase/postgrest-js
@supabase/realtime-js
@supabase/storage-js
@supabase/supabase-js
commit: |
Contributor
Author
|
Thanks for the review and merge, @kallebysantos! 🙌 |
This was referenced Jul 21, 2026
mandarini
pushed a commit
to supabase/supabase
that referenced
this pull request
Jul 22, 2026
This PR updates @supabase/*-js libraries to version 2.110.8. **Source**: supabase-js-stable-release **Changes**: - Updated @supabase/supabase-js to 2.110.8 - Updated @supabase/auth-js to 2.110.8 - Updated @supabase/realtime-js to 2.110.8 - Updated @supabase/postgest-js to 2.110.8 - Refreshed pnpm-lock.yaml --- ## Release Notes ## v2.110.8 ## 2.110.8 (2026-07-21) ### 🩹 Fixes - **auth:** downgrade aborted/transient fetch failures from console.error to warn ([#2544](supabase/supabase-js#2544)) - **functions:** clean up cross-signal abort listener on invoke() return ([#2487](supabase/supabase-js#2487)) - **functions:** match response Content-Type case-insensitively ([#2515](supabase/supabase-js#2515)) - **storage:** url-encode object key in CDN purge methods ([#2545](supabase/supabase-js#2545)) - **supabase:** skip Node warning in Deno ([#2541](supabase/supabase-js#2541)) ### ❤️ Thank You - Franco Kaddour @FrancoKaddour - Katerina Skroumpelou @mandarini - Pedro Henrique - Vaibhav @7ttp ## v2.110.7 ## 2.110.7 (2026-07-16) ### 🩹 Fixes - **postgrest:** correct self-reference inference ([#2525](supabase/supabase-js#2525)) - **realtime:** trigger set auth on INITIAL_SESSION event ([#2531](supabase/supabase-js#2531)) - **realtime:** update phoenix to fix presence issue ([#2532](supabase/supabase-js#2532)) ### ❤️ Thank You - Eduardo Gurgel - Filipe Cabaço @filipecabaco - Vaibhav @7ttp This PR was created automatically. Co-authored-by: supabase-workflow-trigger[bot] <266661614+supabase-workflow-trigger[bot]@users.noreply.github.com>
mandarini
pushed a commit
to supabase/ssr
that referenced
this pull request
Jul 22, 2026
This PR updates `@supabase/supabase-js` to v2.110.8. **Source**: supabase-js-stable-release --- ## Release Notes ## v2.110.8 ## 2.110.8 (2026-07-21) ### 🩹 Fixes - **auth:** downgrade aborted/transient fetch failures from console.error to warn ([#2544](supabase/supabase-js#2544)) - **functions:** clean up cross-signal abort listener on invoke() return ([#2487](supabase/supabase-js#2487)) - **functions:** match response Content-Type case-insensitively ([#2515](supabase/supabase-js#2515)) - **storage:** url-encode object key in CDN purge methods ([#2545](supabase/supabase-js#2545)) - **supabase:** skip Node warning in Deno ([#2541](supabase/supabase-js#2541)) ### ❤️ Thank You - Franco Kaddour @FrancoKaddour - Katerina Skroumpelou @mandarini - Pedro Henrique - Vaibhav @7ttp This PR was created automatically. Co-authored-by: supabase-workflow-trigger[bot] <266661614+supabase-workflow-trigger[bot]@users.noreply.github.com>
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.
When invoke() is called with both timeout and signal, an event listener is registered on the caller's AbortSignal to forward aborts to the internal timeoutController. That listener was never removed, so callers that reuse the same AbortController across multiple invocations accumulate dangling listeners — keeping the timeoutController alive indefinitely.
Root cause: the listener was created as an inline arrow function () => timeoutController!.abort()), so no reference existed to pass to removeEventListener.
Fix: store the listener in onAbort before registering it, and call options.signal?.removeEventListener('abort', onAbort) in the finally block so it's cleaned up on every code path (success, error, and abort).
Two unit tests are included that assert the same function reference is passed to both addEventListener and removeEventListener.