Hmbown/CodeWhale · error
credential file is not valid credential JSON
Error message
credential file {} is not valid credential JSON What it means
parse_auth_file deserializes the credential store file with serde_json before interpreting it as a map of credential entries. If the file content is not parseable JSON at all, this error names the offending path (OS-quoted). It guards against corrupt or hand-edited credential stores.
Solutions
- Open the quoted file and fix the JSON syntax, or delete the file and re-run the provider's login command to regenerate it.
- Restore the file from a backup or dotfile repo.
- Re-authenticate: run the provider's relogin hint (e.g. `grok login` or `codewhale auth ...`).
Example fix
// before: credentials.json contains
{ "xai": { "access_token": "..., // trailing comment, invalid JSON
// after
{ "xai": { "access_token": "..." } } Defensive patterns
Strategy: validation
Validate before calling
const txt = fs.readFileSync(p, 'utf8'); try { JSON.parse(txt); } catch { fixOrDelete(p); } Type guard
const isJson = (s) => { try { JSON.parse(s); return true; } catch { return false; } }; Try / catch
try { useCredentials(); } catch (e) { if (String(e).includes('not valid credential JSON')) { fs.rmSync(path); await relogin(); } } Prevention
- Never hand-edit credential files; use the auth commands
- Validate JSON after any manual edit with a parser before running
- Exclude the credentials dir from partial-sync tools or ensure atomic writes
When it happens
Trigger: load/store code calls parse_auth_file with file contents that serde_json::from_str rejects — truncated writes, manual edits, binary content, or a placeholder written by another tool.
Common situations: Editing ~/.codewhale credentials by hand and leaving invalid JSON; disk-full or crash mid-write leaving a truncated file; a sync tool (dotfiles manager) replacing the file with a template.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- agy OAuth token JSON carries no access token member
- Codex credential file
- 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/48324c590997afef.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/oauth.rs:1719
let Some(raw) = crate::external_credentials::read_codewhale_owned_to_string(path)? else {
return Ok(None);
};
parse_auth_file(&raw, path).map(Some)
}
fn load_owned_auth_file_from_store(
store: &codewhale_config::XaiOAuthCredentialStore,
name: &str,
) -> Result<Option<AuthFile>> {
let Some(raw) = store.read_to_string(name)? else {
return Ok(None);
};
parse_auth_file(&raw, &store.path_for(name)?).map(Some)
}
fn parse_auth_file(raw: &str, path: &Path) -> Result<AuthFile> {
let value: Value = serde_json::from_str(raw).map_err(|_| {
anyhow::anyhow!(
"credential file {} is not valid credential JSON",
codewhale_config::quote_os_path(path)
)
})?;
let obj = value.as_object().ok_or_else(|| {
anyhow::anyhow!(
"credential file {} must be a JSON object of entries",
codewhale_config::quote_os_path(path)
)
})?;
let mut out = BTreeMap::new();
for (k, v) in obj {
match serde_json::from_value::<OwnedAuthEntry>(v.clone()) {
Ok(entry) => {
out.insert(k.clone(), entry);
}
Err(_) => {
tracing::warn!(View on GitHub (pinned to 73e0f67d83)