Version: @useupup/core@3.3.0, @useupup/react@3.3.0 (the only version published on either scope, 2026-09-02).
Reproduce. Mount UpupUploader with sources: ['local','oneDrive'] and a oneDrive.clientId whose tenant requires admin consent (any Microsoft work account with the default user-consent policy will do). Open the OneDrive tile, then decline or close the Microsoft consent screen.
Expected. Something that names what happened: sign-in was cancelled / not granted.
Actual. The picker shows Couldn't load files: Popup was blocked by the browser. Nothing was blocked, and the message sends the user into their browser's popup settings over a choice they made themselves.
Seen on production on 2026-09-08, after Microsoft answered the consent request with a tenant admin-approval wall and the person declined it.
Why it happens — three things compounding, all read out of the published dist:
packages/react/src/components/shared/DriveAuthFallback.tsx (dist/chunk-6TFTTLOD.js:31) auto-triggers auth on mount:
useEffect(() => {
if (attemptedRef.current || error) return
attemptedRef.current = true
onRetry()
}, [error, onRetry])
packages/react/src/components/OneDriveUploader.tsx (dist/OneDriveUploader-I25Y6AJP.js:151) renders that fallback without passing error — it stays inside the ...uploaderProps rest and is never forwarded — so the || error guard can never fire. Dropbox and Box render the same way. A decline drives isLoading false, the fallback re-mounts with a fresh attemptedRef, and it retries by itself.
- That retry's
window.open runs with no transient user activation left, returns null, and packages/core/src/drives/popup-oauth-plugin.ts (dist/chunk-PMBR3OUW.js:944-956) reports the block — truthful about its own call, misleading about the user.
Two smaller things in the same path:
- The decline is never surfaced at all. The popup poll only accepts
href.startsWith(redirectUri) && href.includes('code='); an ?error=access_denied redirect falls through, and closing the window resolve()s silently with no error and no state.
popup-oauth-plugin.ts throws the English literal 'Popup was blocked by the browser' while the catalogue already ships errors.popupBlocked ("Popup blocked", translated into nine locales) — so this string is never localised, and it is the one users actually see through driveBrowser.loadError's {message}.
Host apps cannot work around it. onError is (errorMessage: string) => void and is subscribed to upload failures only (dist/internal.js:543); the six drive events are bound to DriveBrowserController's internal handler (dist/internal.js:1187) and never reach the host, so there is no typed error, no UpupErrorCode, and nothing to branch on. Overriding driveBrowser.loadError through i18n.overrides only changes the wrapper around the same misleading {message}.
Suggested fix.
- Forward
error into DriveAuthFallback from all four drive components so its existing guard works.
- Do not auto-retry a popup after the first attempt — a second
window.open outside a gesture cannot succeed, so retrying only manufactures a false popup-blocked report.
- Read
error / error_description off the redirect and emit a distinct cancellation, and treat a closed popup as a cancellation rather than a silent resolve.
- Throw
errors.popupBlocked through the translator rather than an English literal.
What the reporter did instead. An i18n.overrides entry on driveBrowser.loadError that still prints the library's {message} verbatim and asserts no cause of its own — copy, not a fix, and marked as such in the source. It is deleted the day upstream reports a decline as a decline. No node_modules patch and no fork.
Version:
@useupup/core@3.3.0,@useupup/react@3.3.0(the only version published on either scope,2026-09-02).Reproduce. Mount
UpupUploaderwithsources: ['local','oneDrive']and aoneDrive.clientIdwhose tenant requires admin consent (any Microsoft work account with the default user-consent policy will do). Open the OneDrive tile, then decline or close the Microsoft consent screen.Expected. Something that names what happened: sign-in was cancelled / not granted.
Actual. The picker shows
Couldn't load files: Popup was blocked by the browser. Nothing was blocked, and the message sends the user into their browser's popup settings over a choice they made themselves.Seen on production on 2026-09-08, after Microsoft answered the consent request with a tenant admin-approval wall and the person declined it.
Why it happens — three things compounding, all read out of the published dist:
packages/react/src/components/shared/DriveAuthFallback.tsx(dist/chunk-6TFTTLOD.js:31) auto-triggers auth on mount:packages/react/src/components/OneDriveUploader.tsx(dist/OneDriveUploader-I25Y6AJP.js:151) renders that fallback without passingerror— it stays inside the...uploaderPropsrest and is never forwarded — so the|| errorguard can never fire. Dropbox and Box render the same way. A decline drivesisLoadingfalse, the fallback re-mounts with a freshattemptedRef, and it retries by itself.window.openruns with no transient user activation left, returnsnull, andpackages/core/src/drives/popup-oauth-plugin.ts(dist/chunk-PMBR3OUW.js:944-956) reports the block — truthful about its own call, misleading about the user.Two smaller things in the same path:
href.startsWith(redirectUri) && href.includes('code='); an?error=access_deniedredirect falls through, and closing the windowresolve()s silently with no error and no state.popup-oauth-plugin.tsthrows the English literal'Popup was blocked by the browser'while the catalogue already shipserrors.popupBlocked("Popup blocked", translated into nine locales) — so this string is never localised, and it is the one users actually see throughdriveBrowser.loadError's{message}.Host apps cannot work around it.
onErroris(errorMessage: string) => voidand is subscribed to upload failures only (dist/internal.js:543); the six drive events are bound toDriveBrowserController's internal handler (dist/internal.js:1187) and never reach the host, so there is no typed error, noUpupErrorCode, and nothing to branch on. OverridingdriveBrowser.loadErrorthroughi18n.overridesonly changes the wrapper around the same misleading{message}.Suggested fix.
errorintoDriveAuthFallbackfrom all four drive components so its existing guard works.window.openoutside a gesture cannot succeed, so retrying only manufactures a false popup-blocked report.error/error_descriptionoff the redirect and emit a distinct cancellation, and treat a closed popup as a cancellation rather than a silent resolve.errors.popupBlockedthrough the translator rather than an English literal.What the reporter did instead. An
i18n.overridesentry ondriveBrowser.loadErrorthat still prints the library's{message}verbatim and asserts no cause of its own — copy, not a fix, and marked as such in the source. It is deleted the day upstream reports a decline as a decline. Nonode_modulespatch and no fork.