Three layered protections: a one-shot re-login on 401, a one-shot retry after a short delay on 5xx, and a hard client-side timeout with a jittered retry. Non-JSON and HTML responses are treated as transient rather than passed through as data.
Also called: SmartBuild 401 · spinner never stops · estimator timed out · pull latest hangs
- 1A call uses the cached token; a 401 invalidates it, re-logs in and retries exactly once.
- 2A 5xx waits 400ms and retries once.
- 3The client wraps every call in a 30-second abort controller.
- 4An HTML body (auth redirect or a rebuild) is classed transient and retried once with backoff and jitter.
- 5Anything still failing surfaces as an error toast rather than a hang.
Each protection has a recorded cause. Token revocation: tokens 'can be revoked server-side earlier (password rotation, admin force-logout, server reset). Callers must call invalidateToken() on a 401 so the next request triggers a fresh /login instead of replaying a dead token until our local 23h expiry ticks over.' Server flakes: 'SmartBuild's API has shown intermittent 500-empty responses on read endpoints (GetStartingModel especially) for calls that succeeded moments earlier with identical inputs.' And the timeout is named after the bug it killed: 'the "Pull latest from SmartBuild" infinite-spinner bug. Without it, a fetch that never resolves left syncFromSmartBuild stuck.'
- A revoked token was replayed for up to 23 hours.
- Intermittent upstream 500s failed user actions that would have succeeded on retry.
- A hung upstream left the sync spinner running forever.
See it on your own jobs
Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.
or keep browsing features →