Hmbown/CodeWhale · error · anyhow::Error

The Codewhale account session expired. Run `codewhale…

Error message

The Codewhale account session expired. Run `codewhale login` again

What it means

After the refresh transaction runs, the CLI checks whether it actually obtained a renewed session; if the transaction returned None (no stored refresh bundle left to spend), it reports that the Codewhale account session has expired and the user must log in again. There is no usable refresh token locally, so automatic renewal cannot continue.

Solutions

  1. Run `codewhale login` again to establish a fresh session.
  2. Verify the correct profile is selected; account commands are profile-scoped.
  3. Check that the account store file was not deleted or reset between commands.

Example fix

// shell
// before: codewhale account pull -> session expired
codewhale login
codewhale account pull
Defensive patterns

Strategy: try-catch

Validate before calling

// Check a session exists before running authenticated commands
if !Path::new(account_store_path).exists() {
    eprintln!("No Codewhale session; run `codewhale login` first.");
}

Try / catch

match result {
    Err(e) if e.to_string().contains("session expired") => {
        // terminal: re-authenticate interactively, then retry once
        run_login_interactively()?;
        retry_command()?;
    }
    r => r?,
}

Prevention

When it happens

Trigger: Any authenticated cloud command when the account store transaction yields no renewed session — the stored refresh bundle was already consumed or removed (logout elsewhere, or a prior rotation whose result was never persisted).

Common situations: Long-lived machine where the stored session predates a re-login from another process; the refresh token was rotated by a previous command that crashed before persisting; local account state was cleared or reset.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/41d2449c174f5dc4. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/cloud.rs:595

                    401 => {
                        transaction.clear();
                        return Ok(None);
                    }
                    _ => return Err(response_error(&refresh)),
                }
                let mut next: AuthBundle = parse_json_body(&refresh.body)?;
                validate_auth_bundle(&next)?;
                if next.user.is_none() {
                    next.user = stored.bundle.user.take();
                }
                if next.session.is_none() {
                    next.session = stored.bundle.session.take();
                }
                transaction.replace(next.clone())?;
                Ok(Some((next, transaction.snapshot())))
            })?;
        let Some((next, next_snapshot)) = renewed else {
            bail!("The Codewhale account session expired. Run `codewhale login` again");
        };
        // The rotated token is durable before a potentially failing retry.
        let retried = self.transport.execute(CloudRequest {
            method,
            path: path.into(),
            bearer: Some(next.access_token),
            body,
        })?;
        if retried.status == 401 {
            self.account_store.clear_if_unchanged(&next_snapshot)?;
            bail!("The Codewhale account session expired. Run `codewhale login` again");
        }
        Ok((retried, next_snapshot))
    }

    /// Whether an interactive session exists for this profile and origin.
    ///
    /// A management command asks this before it asks anything of the network,

View on GitHub (pinned to 73e0f67d83)