Skip to content

fix: read abort reasons from captured signals - #1994

Merged
mcintyre94 merged 1 commit into
anza-xyz:mainfrom
matusbalascak:fix/null-abort-event-target
Aug 26, 2026
Merged

mcintyre94 merged 1 commit into
anza-xyz:mainfrom
matusbalascak:fix/null-abort-event-target

Conversation

@matusbalascak

@matusbalascak matusbalascak commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor

Problem

In React Native 0.86, the abort event passed to the RPC coalescer can have target === null. Reading event.target.reason then throws: TypeError: Cannot read property 'reason' of null

I ran into this while testing Solana transaction confirmation in Trezor Suite: trezor/trezor-suite#30691

The timeout confirmation code used the same pattern.

Summary of Changes

Use the abort signal already in scope instead of reading it from the event. Added regression tests for both places.

I ran the node and browser tests, typecheck, lint, and Prettier for both affected packages.

@changeset-bot

changeset-bot Bot commented Aug 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: fcfb7a5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 48 packages
Name Type
@solana/rpc Patch
@solana/transaction-confirmation Patch
@solana/kit Patch
@solana/rpc-graphql Patch
@solana/react Patch
@solana/accounts Patch
@solana/addresses Patch
@solana/assertions Patch
@solana/codecs-core Patch
@solana/codecs-data-structures Patch
@solana/codecs-numbers Patch
@solana/codecs-strings Patch
@solana/codecs Patch
@solana/compat Patch
@solana/errors Patch
@solana/fast-stable-stringify Patch
@solana/fixed-points Patch
@solana/functional Patch
@solana/instruction-plans Patch
@solana/instructions Patch
@solana/keys Patch
@solana/nominal-types Patch
@solana/offchain-messages Patch
@solana/options Patch
@solana/plugin-core Patch
@solana/plugin-interfaces Patch
@solana/program-client-core Patch
@solana/programs Patch
@solana/promises Patch
@solana/rpc-api Patch
@solana/rpc-parsed-types Patch
@solana/rpc-spec-types Patch
@solana/rpc-spec Patch
@solana/rpc-subscriptions-api Patch
@solana/rpc-subscriptions-channel-websocket Patch
@solana/rpc-subscriptions-spec Patch
@solana/rpc-subscriptions Patch
@solana/rpc-transformers Patch
@solana/rpc-transport-http Patch
@solana/rpc-types Patch
@solana/signers Patch
@solana/subscribable Patch
@solana/sysvars Patch
@solana/transaction-introspection Patch
@solana/transaction-messages Patch
@solana/transactions Patch
@solana/wallet-account-signer Patch
@solana/webcrypto-ed25519-polyfill Patch

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

@mcintyre94

Copy link
Copy Markdown
Member

@trevor-cortex

@trevor-cortex trevor-cortex left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Works around a React Native 0.86 quirk where the abort event delivered to a listener can have target === null, which made (e.target as AbortSignal).reason throw. Both call sites now read .reason from the signal already captured in scope (signal in the RPC request coalescer, callerAbortSignal in the timeout confirmation strategy), and regression tests simulate the null-target event in both packages.

Why this is correct

In both cases the listener is registered directly on the same signal object that's now being read. Per spec, e.target for an abort event is that signal, so signal.reason is semantically identical to the old expression in conforming environments — and it keeps working where the event implementation fails to set target. Dropping the now-unused e parameter is the right cleanup, and the as AbortSignal casts go away as a bonus.

The tests take the only realistic route to reproduce this in Node: spy out addEventListener, capture the handler, and invoke it manually with a synthetic Event('abort') whose target is asserted to be null before the handler runs. Aborting the controller first ensures signal.reason is populated, mirroring the real-world sequence. Slightly implementation-coupled, but appropriate here.

Changeset with patch bumps for @solana/rpc and @solana/transaction-confirmation matches the scope of the fix.

Notes for other reviewers

  • It may be worth a quick repo-wide grep for other abort listeners reading e.target (e.g. in the subscriptions or WebSocket packages) so the same RN issue doesn't resurface elsewhere. This PR fixes the two sites named in the linked issue.
  • No behavioral change for platforms with conforming AbortSignal implementations — this is purely a defensive source change.

LGTM — would approve, but I don't have approval rights on this repo.

@bundlemon

bundlemon Bot commented Aug 26, 2026

Copy link
Copy Markdown

BundleMon

Unchanged files (150)
Status Path Size Limits
✅ @solana/kit production bundle
kit/dist/index.production.min.js
56KB -
✅ errors/dist/index.node.mjs
21.85KB -
✅ errors/dist/index.browser.mjs
21.82KB -
✅ errors/dist/index.native.mjs
21.82KB -
✅ rpc-graphql/dist/index.browser.mjs
18.87KB -
✅ rpc-graphql/dist/index.native.mjs
18.87KB -
✅ rpc-graphql/dist/index.node.mjs
18.86KB -
✅ wallet-account-signer/dist/index.node.mjs
18.53KB -
✅ wallet-account-signer/dist/index.native.mjs
18.51KB -
✅ wallet-account-signer/dist/index.browser.mjs
18.51KB -
✅ transaction-messages/dist/index.browser.mjs
11.34KB -
✅ transaction-messages/dist/index.native.mjs
11.34KB -
✅ transaction-messages/dist/index.node.mjs
11.34KB -
✅ instruction-plans/dist/index.browser.mjs
7.06KB -
✅ instruction-plans/dist/index.native.mjs
7.06KB -
✅ instruction-plans/dist/index.node.mjs
7.06KB -
✅ react/dist/index.browser.mjs
5.32KB -
✅ react/dist/index.native.mjs
5.32KB -
✅ react/dist/index.node.mjs
5.32KB -
✅ codecs-data-structures/dist/index.browser.mjs
5.29KB -
✅ codecs-data-structures/dist/index.native.mjs
5.29KB -
✅ codecs-data-structures/dist/index.node.mjs
5.29KB -
✅ offchain-messages/dist/index.browser.mjs
5.25KB -
✅ offchain-messages/dist/index.native.mjs
5.24KB -
✅ offchain-messages/dist/index.node.mjs
5.24KB -
✅ fixed-points/dist/index.browser.mjs
5.08KB -
✅ fixed-points/dist/index.native.mjs
5.07KB -
✅ fixed-points/dist/index.node.mjs
5.07KB -
✅ kit/dist/index.browser.mjs
4.69KB -
✅ kit/dist/index.native.mjs
4.69KB -
✅ kit/dist/index.node.mjs
4.69KB -
✅ transactions/dist/index.browser.mjs
4.05KB -
✅ transactions/dist/index.native.mjs
4.05KB -
✅ transactions/dist/index.node.mjs
4.05KB -
✅ codecs-core/dist/index.browser.mjs
3.62KB -
✅ codecs-core/dist/index.native.mjs
3.62KB -
✅ codecs-core/dist/index.node.mjs
3.62KB -
✅ webcrypto-ed25519-polyfill/dist/index.node.mj
s
3.61KB -
✅ webcrypto-ed25519-polyfill/dist/index.browser
.mjs
3.59KB -
✅ webcrypto-ed25519-polyfill/dist/index.native.
mjs
3.57KB -
✅ rpc-subscriptions/dist/index.browser.mjs
3.37KB -
✅ rpc-subscriptions/dist/index.node.mjs
3.34KB -
✅ rpc-subscriptions/dist/index.native.mjs
3.31KB -
✅ signers/dist/index.browser.mjs
3.26KB -
✅ signers/dist/index.native.mjs
3.26KB -
✅ signers/dist/index.node.mjs
3.26KB -
✅ subscribable/dist/index.node.mjs
3.13KB -
✅ rpc-transformers/dist/index.browser.mjs
3.1KB -
✅ rpc-transformers/dist/index.native.mjs
3.1KB -
✅ rpc-transformers/dist/index.node.mjs
3.1KB -
✅ keys/dist/index.node.mjs
3.06KB -
✅ subscribable/dist/index.native.mjs
3.06KB -
✅ subscribable/dist/index.browser.mjs
3.05KB -
✅ addresses/dist/index.browser.mjs
2.93KB -
✅ addresses/dist/index.native.mjs
2.92KB -
✅ addresses/dist/index.node.mjs
2.92KB -
✅ keys/dist/index.browser.mjs
2.85KB -
✅ keys/dist/index.native.mjs
2.85KB -
✅ transaction-introspection/dist/index.browser.
mjs
2.73KB -
✅ transaction-introspection/dist/index.native.m
js
2.73KB -
✅ transaction-introspection/dist/index.node.mjs
2.73KB -
✅ codecs-strings/dist/index.browser.mjs
2.64KB -
✅ codecs-strings/dist/index.node.mjs
2.5KB -
✅ codecs-strings/dist/index.native.mjs
2.47KB -
✅ transaction-confirmation/dist/index.node.mjs
2.42KB -
✅ transaction-confirmation/dist/index.native.mj
s
2.37KB -
✅ sysvars/dist/index.browser.mjs
2.37KB -
✅ sysvars/dist/index.native.mjs
2.37KB -
✅ sysvars/dist/index.node.mjs
2.37KB -
✅ transaction-confirmation/dist/index.browser.m
js
2.36KB -
✅ rpc-subscriptions-spec/dist/index.node.mjs
2.33KB -
✅ rpc-subscriptions-spec/dist/index.native.mjs
2.29KB -
✅ rpc-subscriptions-spec/dist/index.browser.mjs
2.29KB -
✅ codecs-numbers/dist/index.browser.mjs
1.95KB -
✅ codecs-numbers/dist/index.native.mjs
1.95KB -
✅ codecs-numbers/dist/index.node.mjs
1.94KB -
✅ rpc/dist/index.node.mjs
1.94KB -
✅ rpc-types/dist/index.browser.mjs
1.9KB -
✅ rpc-types/dist/index.native.mjs
1.9KB -
✅ rpc-types/dist/index.node.mjs
1.9KB -
✅ rpc-transport-http/dist/index.browser.mjs
1.89KB -
✅ rpc-transport-http/dist/index.native.mjs
1.89KB -
✅ rpc/dist/index.native.mjs
1.8KB -
✅ rpc/dist/index.browser.mjs
1.79KB -
✅ rpc-transport-http/dist/index.node.mjs
1.71KB -
✅ rpc-spec-types/dist/index.browser.mjs
1.54KB -
✅ rpc-spec-types/dist/index.native.mjs
1.54KB -
✅ rpc-spec-types/dist/index.node.mjs
1.54KB -
✅ rpc-subscriptions-channel-websocket/dist/inde
x.node.mjs
1.33KB -
✅ rpc-subscriptions-channel-websocket/dist/inde
x.native.mjs
1.27KB -
✅ rpc-subscriptions-channel-websocket/dist/inde
x.browser.mjs
1.26KB -
✅ program-client-core/dist/index.browser.mjs
1.21KB -
✅ program-client-core/dist/index.native.mjs
1.21KB -
✅ program-client-core/dist/index.node.mjs
1.21KB -
✅ plugin-core/dist/index.browser.mjs
1.18KB -
✅ plugin-core/dist/index.native.mjs
1.18KB -
✅ plugin-core/dist/index.node.mjs
1.18KB -
✅ options/dist/index.browser.mjs
1.18KB -
✅ options/dist/index.native.mjs
1.18KB -
✅ options/dist/index.node.mjs
1.17KB -
✅ accounts/dist/index.browser.mjs
1.17KB -
✅ accounts/dist/index.native.mjs
1.17KB -
✅ accounts/dist/index.node.mjs
1.16KB -
✅ rpc-api/dist/index.browser.mjs
1.04KB -
✅ rpc-api/dist/index.native.mjs
1.04KB -
✅ rpc-api/dist/index.node.mjs
1.04KB -
✅ compat/dist/index.browser.mjs
969B -
✅ compat/dist/index.native.mjs
968B -
✅ compat/dist/index.node.mjs
966B -
✅ rpc-spec/dist/index.browser.mjs
928B -
✅ rpc-spec/dist/index.native.mjs
928B -
✅ rpc-spec/dist/index.node.mjs
926B -
✅ promises/dist/index.native.mjs
841B -
✅ promises/dist/index.node.mjs
840B -
✅ promises/dist/index.browser.mjs
839B -
✅ rpc-subscriptions-api/dist/index.browser.mjs
810B -
✅ rpc-subscriptions-api/dist/index.native.mjs
808B -
✅ rpc-subscriptions-api/dist/index.node.mjs
807B -
✅ assertions/dist/index.browser.mjs
783B -
✅ instructions/dist/index.browser.mjs
771B -
✅ instructions/dist/index.native.mjs
770B -
✅ instructions/dist/index.node.mjs
768B -
✅ fast-stable-stringify/dist/index.browser.mjs
726B -
✅ fast-stable-stringify/dist/index.native.mjs
725B -
✅ assertions/dist/index.native.mjs
724B -
✅ fast-stable-stringify/dist/index.node.mjs
724B -
✅ assertions/dist/index.node.mjs
723B -
✅ programs/dist/index.browser.mjs
329B -
✅ programs/dist/index.native.mjs
327B -
✅ programs/dist/index.node.mjs
325B -
✅ fs-impl/dist/index.browser.mjs
245B -
✅ event-target-impl/dist/index.node.mjs
230B -
✅ functional/dist/index.browser.mjs
154B -
✅ functional/dist/index.native.mjs
152B -
✅ text-encoding-impl/dist/index.native.mjs
152B -
✅ functional/dist/index.node.mjs
151B -
✅ codecs/dist/index.browser.mjs
145B -
✅ codecs/dist/index.native.mjs
144B -
✅ codecs/dist/index.node.mjs
142B -
✅ event-target-impl/dist/index.browser.mjs
133B -
✅ ws-impl/dist/index.node.mjs
131B -
✅ text-encoding-impl/dist/index.browser.mjs
122B -
✅ fs-impl/dist/index.node.mjs
120B -
✅ text-encoding-impl/dist/index.node.mjs
119B -
✅ ws-impl/dist/index.browser.mjs
113B -
✅ crypto-impl/dist/index.node.mjs
111B -
✅ crypto-impl/dist/index.browser.mjs
109B -
✅ rpc-parsed-types/dist/index.browser.mjs
66B -
✅ rpc-parsed-types/dist/index.native.mjs
65B -
✅ rpc-parsed-types/dist/index.node.mjs
63B -

Total files change -40B -0.01%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

@mcintyre94 mcintyre94 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this!

@mcintyre94
mcintyre94 enabled auto-merge August 26, 2026 18:05
@mcintyre94
mcintyre94 added this pull request to the merge queue Aug 26, 2026
Merged via the queue into anza-xyz:main with commit 490ac9e Aug 26, 2026
11 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Because there has been no activity on this PR for 14 days since it was merged, it has been automatically locked. Please open a new issue if it requires a follow up.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Sep 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants