Skip to content

GIS script-load failure: actionable Drive-save error (lazy-load audit: already correct) - #65

Merged
WilfordGrimley merged 1 commit into
masterfrom
claude/gis-drive-save-error-ux
Jul 18, 2026
Merged

GIS script-load failure: actionable Drive-save error (lazy-load audit: already correct)#65
WilfordGrimley merged 1 commit into
masterfrom
claude/gis-drive-save-error-ux

Conversation

@WilfordGrimley

Copy link
Copy Markdown

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 blocking accounts.google.com — a real occurrence, not hypothetical).

a. Actionable error message. frontend/src/features/googleDrive/googleDriveAuth.ts's injectScript now rejects with a new GSIScriptLoadError instead of a plain Error wrapping the raw URL. The message explains the likely cause (privacy browser/ad blocker) and gives two ways forward: allow accounts.google.com and retry, or just download the PDF instead of saving to Drive. No other code changed — the existing useSaveToDrivePDF catch handler in PDFGenerator.tsx already surfaces reason.message verbatim in the toast, so the better message flows through automatically.

b. Lazy-load audit. Traced requestGoogleDriveWriteToken's only call site (PDFGenerator.tsx's saveToDrivePDF, 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 own show prop, so it's lazy too, though that's a different library-managed code path outside this item's scope.

docs/features/google-drive-connect.md updated in place under "Save PDF directly to Google Drive" with both the lazy-load confirmation and the new error class.

Checklist

  • I have installed pre-commit and installed the hooks with pre-commit install before creating any commits.
  • I have updated any related tests for code I modified or added new tests where appropriate. New googleDriveAuth.test.ts: one test confirming a successful GSI load still resolves with the access token, one confirming a script-load failure rejects with GSIScriptLoadError and the actionable message.
  • I have manually tested my changes as follows:
    • npx tsc --noEmit clean.
    • npx eslint on both files: 0 errors/warnings.
    • npx prettier@2.7.1 --check clean.
    • npx jest --runInBand src/features/googleDrive: 15/15 passing (13 pre-existing + 2 new).
    • Full npx jest --runInBand: only the pre-existing, documented QuestionFeed.test.tsx revealCard() flake fails (unrelated, reconfirmed passing in isolation).
  • I have updated any relevant documentation or created new documentation where appropriate. (docs/features/google-drive-connect.md)

Merge-time checklist

  • None — this is a pure error-message/verification change with no owner-only follow-up.

Generated by Claude Code

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.
@WilfordGrimley
WilfordGrimley merged commit 5c0836c into master Jul 18, 2026
6 checks passed
@WilfordGrimley
WilfordGrimley deleted the claude/gis-drive-save-error-ux branch July 18, 2026 17:01
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants