No REST request in the extension has a timeout: CoderApi never sets defaults.timeout on its axios instance and no call site passes one, so axios's default (no timeout) applies everywhere. A request hung across a network drop or system sleep (half-open TCP) never settles.
This silently kills every poller that only schedules its next run after the current request settles:
- Announcements refresh (
src/announcements/manager.ts) — next poll armed in finally after getAppearance().
- Workspaces tree poll (
src/workspace/workspacesProvider.ts, fetchAndRefresh) — maybeScheduleRefresh() runs only after the fetch settles, and this.fetching stays true, which also blocks manual refreshes.
- OAuth background token refresh (
src/oauth/sessionManager.ts, attemptRefreshWithRetry) — retry timer chained on the request settling; its AbortController only aborts on sign-out/dispose, never on time. A hung refresh means tokens silently stop refreshing.
Proposal: set a sensible default timeout on the CoderApi axios instance, with explicit overrides (or exemptions) for legitimately long-running calls such as binary downloads and build/long-poll operations.
Recommended approach
Set a default on the shared instance in CoderApi.create and opt out where a request is legitimately long:
defaults.timeout = 30_000 on the CoderApi axios instance. This covers every SDK call and the OAuth token refresh, which posts through client.getAxiosInstance() (src/oauth/sessionManager.ts), so all three pollers above become hang-proof with one line.
- Pass
{ timeout: 0 } explicitly for the CLI binary download (src/core/cliManager.ts download request with responseType: "stream", same shared instance). Note axios's timeout only bounds time-to-first-response, not body streaming, but the explicit opt-out keeps slow mirrors safe and documents the intent.
- The ad-hoc
globalAxios.create() client in cliManager should get the same 30s default when it is not downloading.
- Workspace build endpoints (
startWorkspace etc.) return as soon as the build is queued (logs stream over websockets), so they need no exemption; verify once in CI against a real deployment before merging.
Timeout errors surface as ECONNABORTED axios errors, so existing errToStr/retry paths handle them like any other network failure.
No REST request in the extension has a timeout:
CoderApinever setsdefaults.timeouton its axios instance and no call site passes one, so axios's default (no timeout) applies everywhere. A request hung across a network drop or system sleep (half-open TCP) never settles.This silently kills every poller that only schedules its next run after the current request settles:
src/announcements/manager.ts) — next poll armed infinallyaftergetAppearance().src/workspace/workspacesProvider.ts,fetchAndRefresh) —maybeScheduleRefresh()runs only after the fetch settles, andthis.fetchingstaystrue, which also blocks manual refreshes.src/oauth/sessionManager.ts,attemptRefreshWithRetry) — retry timer chained on the request settling; itsAbortControlleronly aborts on sign-out/dispose, never on time. A hung refresh means tokens silently stop refreshing.Proposal: set a sensible default
timeouton the CoderApi axios instance, with explicit overrides (or exemptions) for legitimately long-running calls such as binary downloads and build/long-poll operations.Recommended approach
Set a default on the shared instance in
CoderApi.createand opt out where a request is legitimately long:defaults.timeout = 30_000on the CoderApi axios instance. This covers every SDK call and the OAuth token refresh, which posts throughclient.getAxiosInstance()(src/oauth/sessionManager.ts), so all three pollers above become hang-proof with one line.{ timeout: 0 }explicitly for the CLI binary download (src/core/cliManager.tsdownload request withresponseType: "stream", same shared instance). Note axios'stimeoutonly bounds time-to-first-response, not body streaming, but the explicit opt-out keeps slow mirrors safe and documents the intent.globalAxios.create()client incliManagershould get the same 30s default when it is not downloading.startWorkspaceetc.) return as soon as the build is queued (logs stream over websockets), so they need no exemption; verify once in CI against a real deployment before merging.Timeout errors surface as
ECONNABORTEDaxios errors, so existingerrToStr/retry paths handle them like any other network failure.