{"record":{"id":"65cf2675e8b9fb51","repo":"JuliusBrussee/caveman","slug":"caveman-remote-gateway-key-revocation-was-unavail","errorCode":null,"errorMessage":"caveman: remote gateway key revocation was unavailable; credentials kept — retry `caveman logout`","messagePattern":"caveman: remote gateway key revocation was unavailable; credentials kept — retry `caveman logout`","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":9447,"sourceCode":"  }\n  throw new Error(\"device login timed out before approval\");\n}\n\nasync function logout() {\n\tconst cfg = await config();\n\tconst externalToken = Boolean(process.env.CAVE_TOKEN);\n\tif (cfg.token && (!cfg.logoutPendingLocalCleanup || externalToken)) {\n\t  if (cfg.projectId && cfg.gatewayKeyId) {\n\t    let response: Response;\n\t    try {\n\t      response = await fetch(`${cfg.baseURL}/api/v1/projects/${encodeURIComponent(cfg.projectId)}/keys/${encodeURIComponent(cfg.gatewayKeyId)}/revoke`, {\n\t        method: \"POST\",\n\t        headers: { authorization: `Bearer ${cfg.token}`, \"content-type\": \"application/json\", \"x-cave-csrf\": \"cli\" },\n\t        body: \"{}\",\n\t        signal: AbortSignal.timeout(5000),\n\t      });\n\t    } catch {\n\t      throw new Error(\"caveman: remote gateway key revocation was unavailable; credentials kept — retry `caveman logout`\");\n\t    }\n\t    if (!response.ok) {\n\t      const body = await response.json().catch(() => null) as { error?: { code?: unknown } } | null;\n\t      const alreadyRevoked = response.status === 404 && body?.error?.code === \"cave_key_not_found\";\n\t      if (!alreadyRevoked) throw new Error(`caveman: remote gateway key revocation failed (HTTP ${response.status}); credentials kept — retry \\`caveman logout\\``);\n\t    }\n\t  }\n\t  const headers: Record<string, string> = {\n\t    authorization: `Bearer ${cfg.token}`,\n\t    \"x-cave-client\": \"cli\",\n\t  };\n\t  const request: RequestInit = {\n\t    method: \"POST\",\n\t    headers,\n\t    signal: AbortSignal.timeout(5000),\n\t  };\n\t  if (cfg.refreshToken) {\n\t    headers[\"content-type\"] = \"application/json\";","sourceCodeStart":9429,"sourceCodeEnd":9465,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/5184b3d11ac6a1acb7d44b9bfaa31698157cff97/packages/cli/src/index.ts#L9429-L9465","documentation":"During logout, the POST to revoke the remote gateway key could not be completed (network/transport failure); the CLI deliberately keeps local credentials so logout can be retried rather than leaving the key unrevoked and untracked.","triggerScenarios":"Thrown at packages/cli/src/index.ts:8602 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Retry `caveman logout` once connectivity returns","Check server reachability; the key remains valid until revocation succeeds"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"5184b3d11ac6a1acb7d44b9bfaa31698157cff97","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}