JuliusBrussee/caveman · error · Error

caveman: remote gateway key revocation was unavailable; cred

Error message

caveman: remote gateway key revocation was unavailable; credentials kept — retry `caveman logout`

What it means

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.

Source

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

  }
  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`");
	    }
	    if (!response.ok) {
	      const body = await response.json().catch(() => null) as { error?: { code?: unknown } } | null;
	      const alreadyRevoked = response.status === 404 && body?.error?.code === "cave_key_not_found";
	      if (!alreadyRevoked) throw new Error(`caveman: remote gateway key revocation failed (HTTP ${response.status}); credentials kept — retry \`caveman logout\``);
	    }
	  }
	  const headers: Record<string, string> = {
	    authorization: `Bearer ${cfg.token}`,
	    "x-cave-client": "cli",
	  };
	  const request: RequestInit = {
	    method: "POST",
	    headers,
	    signal: AbortSignal.timeout(5000),
	  };
	  if (cfg.refreshToken) {
	    headers["content-type"] = "application/json";

View on GitHub (pinned to 5184b3d11a)

Solutions

  1. Retry `caveman logout` once connectivity returns
  2. Check server reachability; the key remains valid until revocation succeeds
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at packages/cli/src/index.ts:8602 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/65cf2675e8b9fb51. Report an issue: GitHub.