GIS script-load failure: actionable Drive-save error (lazy-load audit: already correct) - #65
Merged
Merged
Conversation
The GSI script (accounts.google.com/gsi/client) is already loaded lazily, only on the first save-to-Drive click - confirmed via requestGoogleDriveWriteToken's only call site (PDFGenerator.tsx's saveToDrivePDF), so there was nothing to convert there. The failure UX itself was the real gap: a browser blocking accounts.google.com (privacy browsers, ad/tracker blockers - a real occurrence, not hypothetical) surfaced as the raw "Failed to load https://accounts.google.com/gsi/client" string in the save-to-Drive toast. injectScript's onerror now rejects with a dedicated GSIScriptLoadError carrying an actionable message instead.
4 tasks
WilfordGrimley
added a commit
that referenced
this pull request
Jul 18, 2026
5 tasks
WilfordGrimley
added a commit
that referenced
this pull request
Jul 18, 2026
…staleness mini-pass (#79) * publish_wiki.py: fix link rewriting for parent-relative paths and slug casing GitHub wiki's native [[...]] auto-linking reinterprets our own docs/ [[file.md]] convention: [[../troubleshooting.md]] became a dead literal slug, and [[printing-tags.md]] linked the raw filename casing instead of the published page name "Printing-Tags" (both visible live on Catalog-Completion-Plan). Every internal link is now resolved against its source file's real repo path and mapped through wiki-publish-map.json: a published target becomes a same-wiki link using its real page name, an unpublished-but-real target becomes an absolute GitHub blob URL, and a target resolving to neither is a hard publish error. docs_lint.py can't catch this class of bug since it only checks links within docs/ itself, not the wiki-transform's own reinterpretation downstream - the script now self-checks at publish time instead. Also adds two docs/ pages that were listed in docs/README.md's index but missing from the mapping entirely (found via the new validation): documentation-process.md and upstream-wiki-drift.md. * Docs staleness pass: Part 3 write-pass status + proposal B/C/E-1/E-2 markers catalog-completion-plan.md: Part 3 heading and Status section updated to reflect the completed write pass (run_id 20260718T145157-a12b1387, 13,275 votes, all hard bounds passed, 0/7,124 zero-resolution violations at full population), pointing to docs/reports/2026-07-18-part3-write-pass-complete.md. Filled the dangling "see the follow-up entry below" reference and replaced the now-stale "HOLD #P3 stands" language. Part 4's heading now notes it's confirmed unstarted with HOLD #B prep queued. proposal-b-bleed-normalization.md: top summary no longer lists the prior-resolution batch fetch as remaining work - it shipped as PR-1 (#72). proposal-g-user-accounts-saved-decks.md: noted the build-order queue (E-1 #61, E-2 #62, Level-2 grid fix #63, audit pass #64, GIS error UX #65, Proposal B #66/#72, Proposal C part (a) #67) has fully cleared. docs/README.md: added proposal-b and proposal-c to the "Plans & proposals" table - both have dedicated docs but were missing from the index entirely, despite the section's own stated policy that any proposal with a dedicated doc gets a row. printing-tags.md and vote-system.md checked per the mini-pass's minimum list; no changes needed - printing-tags.md already defers Stage 8+ status to catalog-completion-plan.md, and vote-system.md has no AI-terminology or merged-PR staleness. * Report relay: wiki review findings (publish-script fix, Part 3 status, staleness mini-pass) * CI: black-format publish_wiki.py, prettier-format cache-transition-resilience.md black reformatting for publish_wiki.py (never run locally - only py_compile was checked, missing the repo's black rev 22.8.0 pinned in .pre-commit-config.yaml). cache-transition-resilience.md's prettier drift predates this PR (introduced by #75) and is unrelated to its content - swept here since the "Formatting and static type checking" check runs pre-commit against all files, not just the diff, and this PR's own CI needs to go green. --------- Co-authored-by: Claude <noreply@anthropic.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.
entry
Description
Two-part item: the Drive-save path was surfacing the raw
"Failed to load https://accounts.google.com/gsi/client"string as the failure toast when the Google Identity Services script can't load (typically a privacy browser or ad/tracker blocker blockingaccounts.google.com— a real occurrence, not hypothetical).a. Actionable error message.
frontend/src/features/googleDrive/googleDriveAuth.ts'sinjectScriptnow rejects with a newGSIScriptLoadErrorinstead of a plainErrorwrapping the raw URL. The message explains the likely cause (privacy browser/ad blocker) and gives two ways forward: allowaccounts.google.comand retry, or just download the PDF instead of saving to Drive. No other code changed — the existinguseSaveToDrivePDFcatch handler inPDFGenerator.tsxalready surfacesreason.messageverbatim in the toast, so the better message flows through automatically.b. Lazy-load audit. Traced
requestGoogleDriveWriteToken's only call site (PDFGenerator.tsx'ssaveToDrivePDF, invoked only from the "Save PDF to Google Drive" button's click handler) — the GSI script is already injected lazily, only on first save-to-Drive click, never on page load or app mount. Nothing to convert; this is already the correct zero-telemetry-posture behavior. Also checked the separate Google Drive picker flow (GoogleDrivePicker.tsx, a different feature using@googleworkspace/drive-picker-react) — its own script loading is gated behind the picker component's ownshowprop, so it's lazy too, though that's a different library-managed code path outside this item's scope.docs/features/google-drive-connect.mdupdated in place under "Save PDF directly to Google Drive" with both the lazy-load confirmation and the new error class.Checklist
pre-commitand installed the hooks withpre-commit installbefore creating any commits.googleDriveAuth.test.ts: one test confirming a successful GSI load still resolves with the access token, one confirming a script-load failure rejects withGSIScriptLoadErrorand the actionable message.npx tsc --noEmitclean.npx eslinton both files: 0 errors/warnings.npx prettier@2.7.1 --checkclean.npx jest --runInBand src/features/googleDrive: 15/15 passing (13 pre-existing + 2 new).npx jest --runInBand: only the pre-existing, documentedQuestionFeed.test.tsxrevealCard()flake fails (unrelated, reconfirmed passing in isolation).docs/features/google-drive-connect.md)Merge-time checklist
Generated by Claude Code