JuliusBrussee/caveman · error

device login timed out before approval

Error message

device login timed out before approval

What it means

Thrown by the CLI device-login (OAuth device flow) loop in `caveman login`. The loop polls the authorization server for approval and exits with this error when the retry budget is exhausted before the user approves the sign-in. It indicates the device code expired or the user never completed browser approval in time.

Solutions

  1. Re-run `caveman login` and approve promptly in the browser when prompted.
  2. Open the verification URL in the default browser immediately (copy the code before it expires).
  3. Check for slow SSO/VPN causing delayed approval; approve on a faster network.
  4. If it repeatedly times out, verify the gateway/auth server is reachable and not rate-limiting (slow_down responses inflate intervalMs).

Example fix

// before: approve hours later after code expiry
caveman login  # ignore prompt, approve 30 min later
// after
caveman login  # approve in browser immediately when the code is shown
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await login();
} catch (e) {
  if (e instanceof Error && e.message === "device login timed out before approval") {
    console.error("Approval not completed in time — re-running login; approve in the browser promptly.");
    return login(); // one bounded retry
  }
  throw e;
}

Prevention

When it happens

Trigger: Running `caveman login` and never visiting the verification URL, visiting it after the device code expired, or the poll loop exceeding its max attempts while `authorization_pending` persists.

Common situations: Developer runs login, gets distracted and doesn't open the browser link; slow corporate SSO approval; stale browser session where the approve button silently fails; polling interval backoff (nextDevicePollIntervalMs) exceeding the server's device-code lifetime.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/4d59091a59c0541c. Report an issue: GitHub.

Appendix: source

Thrown at packages/cli/src/index.ts:9793

      } else if (gateway) {
        console.error(`  ${mark("ok")} connected; wrap routes through ${gateway}`);
      }
      console.error(SYNC_DISCLOSURE);
      print({ authenticated: true, baseURL, gateway_url: gateway || null, organization_id: organizationId ?? null, token_store: tokenStore });
      // The funnel bridge: pull the spans the local proxy already measured into
      // the dashboard, once, right now (always labeled inferred; best-effort).
      await syncAfterLogin();
      return;
    }
    const errorCode = typeof tok.error === "string" ? tok.error : "";
    if (errorCode === "slow_down") {
      intervalMs = nextDevicePollIntervalMs(intervalMs, errorCode);
    } else if (errorCode && errorCode !== "authorization_pending") {
      throw new Error(`device login failed: ${errorCode}`);
    }
    await sleep(Math.max(intervalMs, 200));
  }
  throw new Error("device login timed out before approval");
}

async function logout() {
	const cfg = await config();
	const externalToken = Boolean(process.env.CAVE_TOKEN);
	if (cfg.token && (!cfg.logoutPendingLocalCleanup || externalToken)) {
	  if (cfg.projectId && cfg.gatewayKeyId) {
	    let response: Response;
	    try {
	      response = await fetch(`${cfg.baseURL}/api/v1/projects/${encodeURIComponent(cfg.projectId)}/keys/${encodeURIComponent(cfg.gatewayKeyId)}/revoke`, {
	        method: "POST",
	        headers: { authorization: `Bearer ${cfg.token}`, "content-type": "application/json", "x-cave-csrf": "cli" },
	        body: "{}",
	        signal: AbortSignal.timeout(5000),
	      });
	    } catch {
	      throw new Error("caveman: remote gateway key revocation was unavailable; credentials kept — retry `caveman logout`");
	    }

View on GitHub (pinned to 3ee70a1026)