fix(useScriptTag): handle the auto-load rejection - #206
Merged
childrentime merged 1 commit intoJul 28, 2026
Merged
Conversation
The `immediate` auto-load calls `load()` as a bare statement inside useMount, so nothing is attached to the promise it returns. When the script fails - blocked by an ad blocker, offline, 404 - the DOM error listener rejects that promise and the rejection reaches window.onunhandledrejection, where error trackers report it. Setting `status` to 'error' does not mark the promise handled. Attach `.catch(noop)` to the auto-load. Callers that hold the promise themselves still see the rejection, since `load()` memoizes and returns the same promise. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Faithfinder
force-pushed
the
pr/handle-script-load-rejection
branch
from
July 28, 2026 14:33
64f5f51 to
0579fcf
Compare
childrentime
approved these changes
Jul 28, 2026
childrentime
left a comment
Owner
There was a problem hiding this comment.
Verified locally: both new tests fail on main and pass with the fix; pnpm lint and the full @reactuses/core suite (307 tests) are green.
load().catch(noop) attaches the handler to the memoized _promise.current, so the auto-load no longer surfaces as an unhandled rejection while an explicit load() still rejects for callers that hold it. status === 'error' remains the reporting channel. Minimal and correct — thanks!
childrentime
added a commit
that referenced
this pull request
Jul 28, 2026
Fixes - useScriptTag no longer surfaces an unhandled promise rejection when the `immediate` auto-load fails (ad blocker, offline, 404). The auto-load now attaches a no-op catch; `status === 'error'` stays the reporting channel and an explicit `load()` still rejects for callers holding the promise. Closes #206. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Owner
|
Released in |
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.
Problem
The
immediateauto-load callsload()as a bare statement:Nothing is attached to the promise it returns. When the script fails — blocked by an ad blocker, offline, 404 — the
errorlistener rejects that promise, and with no handler the rejection reacheswindow.onunhandledrejection, where error trackers report it. Settingstatusto'error'does not mark the promise handled;setStatusandrejectare independent.Any
useScriptTagpointing at analytics, a chat widget, or a third-party SDK hits this for every user running a blocklist. In our app it was the single highest-volume Sentry issue — 5231 events across 405 users, from three scripts.Fix
load().catch(noop)in the auto-load path.status === 'error'stays the reporting channel for a load nobody awaited. Callers that hold the promise themselves are unaffected:load()memoizes into_promise.current, so an explicitload()returns the same promise and still rejects for them.Tests
Two added to
useScriptTag/index.spec.ts— one per direction. Both fail onmain, both pass with the fix.One note for review: jest intercepts unhandled rejections at the VM level, so neither
process.on('unhandledRejection')nor the jsdomunhandledrejectionevent can observe them from inside a test — I tried both. Jest's own reporter does fail the suite on one, which is what makes the first test a regression guard rather than just astatusassertion. There's a comment above it saying so, since it isn't obvious from the assertion alone.pnpm lintand the full@reactuses/coresuite (307 tests) pass.Written with Claude Code; I've read and understood every line, per
.claude/ai-policy.md.