{"record":{"id":"6624f1b01db0ca52","repo":"Hmbown/CodeWhale","slug":"the-codewhale-account-session-expired-run-codewh","errorCode":null,"errorMessage":"The Codewhale account session expired. Run `codewhale account login` again","messagePattern":"The Codewhale account session expired\\. Run `codewhale account login` again","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/cli/src/cloud.rs","lineNumber":470,"sourceCode":"            body: body.clone(),\n        })?;\n        if first.status != 401 {\n            return Ok(first);\n        }\n\n        let refresh = self.transport.execute(CloudRequest {\n            method: HttpMethod::Post,\n            path: \"/api/auth/refresh\".to_string(),\n            bearer: None,\n            body: Some(json_body(&RefreshRequest {\n                refresh_token: &stored.bundle.refresh_token,\n            })?),\n        })?;\n        match refresh.status {\n            200 => {}\n            401 => {\n                self.clear_auth()?;\n                bail!(\"The Codewhale account session expired. Run `codewhale account login` again\");\n            }\n            _ => return Err(response_error(&refresh)),\n        }\n        let mut next: AuthBundle = parse_json_body(&refresh.body)?;\n        validate_auth_bundle(&next)?;\n        if next.user.is_none() {\n            next.user = stored.bundle.user.take();\n        }\n        self.save_auth(next.clone())?;\n\n        let retried = self.transport.execute(CloudRequest {\n            method,\n            path: path.to_string(),\n            bearer: Some(next.access_token),\n            body,\n        })?;\n        if retried.status == 401 {\n            self.clear_auth()?;","sourceCodeStart":452,"sourceCodeEnd":488,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/cli/src/cloud.rs#L452-L488","documentation":"When an authenticated call returns 401, the CLI attempts a refresh-token exchange at /api/auth/refresh. If that refresh call itself returns 401, the refresh token is invalid (revoked/expired), so the local session is cleared and this message tells the user to re-authenticate from scratch.","triggerScenarios":"Long-lived session whose access token and refresh token both expired; refresh token revoked server-side (password change, device management); clock skew making the server reject tokens; stale session written by an older CLI against a rotated signing key.","commonSituations":"Returning to a machine after weeks of idle, service-side token rotation/incident, signing in on the same account from a management UI that invalidates old sessions.","solutions":["Run `codewhale account login` again — the old session has already been cleared for you.","If it recurs unusually fast, verify system clock accuracy (NTP) on both client and any proxies.","Check whether your account's security policy revokes CLI sessions (then whitelist or re-authorize periodically).","Update the CLI in case of a token-handling change on the server."],"exampleFix":"# before: stale session keeps failing every command\ncodewhale account me   # 401 -> refresh 401 -> this error\n\n# after\ncodewhale account login\ncodewhale account me","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"match client.execute_authenticated(...).await {\n    Ok(r) => r,\n    Err(e) if e.to_string().contains(\"session expired\") => {\n        // refresh already failed and local session was cleared; only re-login can recover\n        run_login(profile).await?;\n        client.execute_authenticated(...).await\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Expect long-idle sessions to need re-login; script a login check before batch runs.","Keep system clocks NTP-synced so tokens are not rejected early.","Note that this error already cleared the stale session — no manual cleanup needed."],"tags":["authentication","token-refresh","cloud","cli"],"backgroundTag":"refresh-token-expired","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}