JuliusBrussee/caveman · error · Error
device login failed: ${errorCode}
Error message
device login failed: ${errorCode} What it means
The device-login token poll returned a terminal error code from RFC 8628 (e.g. access_denied or expired_token) rather than the retryable authorization_pending/slow_down. The flow has failed and cannot succeed by continued polling; the server's error code is reported.
Source
Thrown at packages/cli/src/index.ts:9426
// effort: login never fails for seats or a down entitlement service.
await fetchAndStoreWrapEntitlement(baseURL, credentials.access_token);
if (gateway && wrapMode(gateway) === "managed") {
console.error(` ${mark("ok")} wrap now routes through the managed gateway (${gateway}) — governed reporting; verified stays zero without qualifying provider evidence`);
} 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),View on GitHub (pinned to 5184b3d11a)
Solutions
- Read errorCode: expired_token → restart login promptly; access_denied → approval was refused
- Restart `caveman login` for a fresh device code
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/cli/src/index.ts:8581 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of JuliusBrussee/caveman@5184b3d11a (2026-08-18).
Data as JSON: /api/errors/6344f5febc395881.
Report an issue: GitHub.