Hmbown/CodeWhale · error
Codewhale-owned OAuth credentials at
Error message
Codewhale-owned OAuth credentials at {} have no usable entry. Run `{hint}` again. What it means
Codewhale manages OAuth credentials in a shared config file keyed by provider and scope. After the file was found, `select_entry` returned no entry usable for the requested provider, meaning the file exists but contains no matching OAuth entry. The library treats this as a corrupt/incomplete Codewhale-owned credential store and asks the user to re-run the login hint command.
Solutions
- Re-run the login command shown by `{hint}` (the codewhale OAuth login hint) to recreate the credential entry.
- Check the file at the printed path and verify it contains an entry for the requested provider.
- Back up and remove the credentials file, then log in again to regenerate it.
- Confirm the provider name passed to the loader matches one stored in the file.
Example fix
// before (stale file with no matching entry) codewhale oauth login --provider anthropic // after (regenerate entry for the provider actually used) rm ~/.codewhale/oauth-credentials.json codewhale oauth login --provider openai
Defensive patterns
Strategy: validation
Validate before calling
use std::path::Path;
fn has_usable_entry(path: &Path, provider: &str) -> bool {
std::fs::read_to_string(path).ok()
.map(|s| s.contains(provider))
.unwrap_or(false)
}
if !has_usable_entry(&cred_path, provider) {
eprintln!("run the oauth login hint first");
return;
} Type guard
fn credentials_file_exists(path: &std::path::Path) -> bool {
path.is_file()
} Try / catch
match load_codewhale_oauth_entry(provider) {
Ok(entry) => use_entry(entry),
Err(e) if e.to_string().contains("no usable entry") => {
prompt_relogin(provider);
}
Err(e) => return Err(e),
} Prevention
- Never hand-edit the Codewhale OAuth credentials file.
- Always use the login hint command to create or refresh entries.
- Check `logout` state before assuming stored credentials exist for a provider.
When it happens
Trigger: Calling the credential-loading path in crates/tui/src/oauth.rs (around line 2243) when the Codewhale OAuth config file exists at `path` but `select_entry(provider, &mut file)` finds no entry matching the provider/scope.
Common situations: The credentials file was hand-edited or truncated, a previous login saved credentials for a different provider, the stored entry was removed by a logout/cleanup, or a schema/version change left the file without the expected entry shape.
Related errors
- restoring retired xAI OAuth file
- agy OAuth token JSON carries no access token member
- agy OAuth token member
- atomically replacing xAI OAuth credentials
- bearer credentials are not an API key
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/440380e1931771ee.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/oauth.rs:2243
fn get_owned_credentials_locked<F>(
provider: OAuthProvider,
store: &codewhale_config::XaiOAuthCredentialStore,
name: &str,
refresh_access: F,
) -> Result<OwnedOAuthCredentials>
where
F: FnOnce(&str, &str, &str) -> Result<OAuthTokenMaterial>,
{
let hint = oauth_provider_params(provider).relogin_hint;
let path = store.path_for(name)?;
let mut file = load_owned_auth_file_from_store(store, name)?.ok_or_else(|| {
anyhow::anyhow!(
"Codewhale-owned OAuth credentials were not found at {}. Run `{hint}` again.",
codewhale_config::quote_os_path(&path)
)
})?;
let (scope, mut entry) = select_entry(provider, &mut file).ok_or_else(|| {
anyhow::anyhow!(
"Codewhale-owned OAuth credentials at {} have no usable entry. Run `{hint}` again.",
codewhale_config::quote_os_path(&path)
)
})?;
if entry_access_token_is_fresh(&entry) {
let token = entry
.access_token
.clone()
.filter(|t| !t.trim().is_empty())
.context("OAuth access token is empty")?;
return Ok(credentials_from_entry(provider, &scope, &entry, token));
}
let refresh = entry
.refresh_token
.as_deref()
.filter(|t| !t.trim().is_empty())View on GitHub (pinned to 73e0f67d83)