{"record":{"id":"440380e1931771ee","repo":"Hmbown/CodeWhale","slug":"codewhale-owned-oauth-credentials-at-have-no-usable-entry","errorCode":null,"errorMessage":"Codewhale-owned OAuth credentials at {} have no usable entry. Run `{hint}` again.","messagePattern":"Codewhale-owned OAuth credentials at (.+?) have no usable entry\\. Run `(.+?)` again\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/oauth.rs","lineNumber":2243,"sourceCode":"fn get_owned_credentials_locked<F>(\n    provider: OAuthProvider,\n    store: &codewhale_config::XaiOAuthCredentialStore,\n    name: &str,\n    refresh_access: F,\n) -> Result<OwnedOAuthCredentials>\nwhere\n    F: FnOnce(&str, &str, &str) -> Result<OAuthTokenMaterial>,\n{\n    let hint = oauth_provider_params(provider).relogin_hint;\n    let path = store.path_for(name)?;\n    let mut file = load_owned_auth_file_from_store(store, name)?.ok_or_else(|| {\n        anyhow::anyhow!(\n            \"Codewhale-owned OAuth credentials were not found at {}. Run `{hint}` again.\",\n            codewhale_config::quote_os_path(&path)\n        )\n    })?;\n    let (scope, mut entry) = select_entry(provider, &mut file).ok_or_else(|| {\n        anyhow::anyhow!(\n            \"Codewhale-owned OAuth credentials at {} have no usable entry. Run `{hint}` again.\",\n            codewhale_config::quote_os_path(&path)\n        )\n    })?;\n\n    if entry_access_token_is_fresh(&entry) {\n        let token = entry\n            .access_token\n            .clone()\n            .filter(|t| !t.trim().is_empty())\n            .context(\"OAuth access token is empty\")?;\n        return Ok(credentials_from_entry(provider, &scope, &entry, token));\n    }\n\n    let refresh = entry\n        .refresh_token\n        .as_deref()\n        .filter(|t| !t.trim().is_empty())","sourceCodeStart":2225,"sourceCodeEnd":2261,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/oauth.rs#L2225-L2261","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (stale file with no matching entry)\ncodewhale oauth login --provider anthropic\n// after (regenerate entry for the provider actually used)\nrm ~/.codewhale/oauth-credentials.json\ncodewhale oauth login --provider openai","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn has_usable_entry(path: &Path, provider: &str) -> bool {\n    std::fs::read_to_string(path).ok()\n        .map(|s| s.contains(provider))\n        .unwrap_or(false)\n}\nif !has_usable_entry(&cred_path, provider) {\n    eprintln!(\"run the oauth login hint first\");\n    return;\n}","typeGuard":"fn credentials_file_exists(path: &std::path::Path) -> bool {\n    path.is_file()\n}","tryCatchPattern":"match load_codewhale_oauth_entry(provider) {\n    Ok(entry) => use_entry(entry),\n    Err(e) if e.to_string().contains(\"no usable entry\") => {\n        prompt_relogin(provider);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["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."],"tags":["oauth","credentials","rust"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}