Hmbown/CodeWhale · error

Codewhale-owned xAI OAuth file

Error message

Codewhale-owned xAI OAuth file {} is not valid UTF-8

What it means

The xAI OAuth credential file exists but its bytes are not valid UTF-8, so it cannot be parsed as the JSON token blob this store expects. The library refuses to return corrupt or binary content from a Codewhale-owned credential file rather than propagate garbage. This is a data-integrity guard during read_to_string.

Solutions

  1. Delete the corrupt file and re-authenticate so the store rewrites it (e.g. rm the path, then run the xAI login/logout flow).
  2. Check the file with `file`/`xxd` to confirm it is non-text, and restore a known-good backup if one exists.
  3. Verify no sync tool or editor is touching ~/.codewhale credentials; exclude the directory from syncing.
  4. Ensure disk health / fsck if corruption is recurring.

Example fix

// before (corrupt file fails)
let token = store.read_to_string("xai.oauth.v1.json")?;
// after (recover by re-creating)
if store.read_to_string("xai.oauth.v1.json").is_err() {
    store.write("xai.oauth.v1.json", fresh_token_bytes, true)?;
}
Defensive patterns

Strategy: try-catch

Validate before calling

let bytes = std::fs::read(&path)?;
anyhow::ensure!(std::str::from_utf8(&bytes).is_ok(), "credential file is not UTF-8; re-authenticate");

Type guard

fn is_utf8_file(path: &Path) -> bool {
    std::fs::read(path).map(|b| std::str::from_utf8(&b).is_ok()).unwrap_or(false)
}

Try / catch

match store.read_to_string(name) {
    Ok(token) => token,
    Err(e) if e.to_string().contains("not valid UTF-8") => {
        // delete and re-authenticate
        let _ = std::fs::remove_file(path);
        reauthenticate()?;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling XaiOAuthCredentialStore::read_to_string when the file at <dir>/<name> contains binary data, partially-written bytes, or a legacy credential written by a different tool with a non-UTF-8 encoding.

Common situations: A crashed/interrupted write left a truncated token file; an editor or sync tool (Dropbox etc.) rewrote the file with a BOM or binary junk; a user manually pasted a token using a tool that wrote raw bytes.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at crates/config/src/xai_credentials.rs:254

        let mut bytes = Vec::with_capacity(metadata.len() as usize);
        (&mut file)
            .take(XAI_OAUTH_FILE_LIMIT + 1)
            .read_to_end(&mut bytes)
            .with_context(|| {
                format!(
                    "reading Codewhale-owned xAI OAuth file {}",
                    crate::quote_os_path(&self.directory.join(name))
                )
            })?;
        if bytes.len() as u64 > XAI_OAUTH_FILE_LIMIT {
            bail!(
                "Codewhale-owned xAI OAuth file {} exceeds the {} byte limit",
                crate::quote_os_path(&self.directory.join(name)),
                XAI_OAUTH_FILE_LIMIT
            );
        }
        String::from_utf8(bytes).map(Some).map_err(|_| {
            anyhow::anyhow!(
                "Codewhale-owned xAI OAuth file {} is not valid UTF-8",
                crate::quote_os_path(&self.directory.join(name))
            )
        })
    }

    pub fn write(&self, name: &str, bytes: &[u8], allow_replace: bool) -> Result<()> {
        validate_owned_auth_name(name)?;
        anyhow::ensure!(
            bytes.len() as u64 <= XAI_OAUTH_FILE_LIMIT,
            "refusing oversized xAI OAuth credential payload"
        );
        self.write_owned_file(name, bytes, allow_replace)
    }

    pub fn remove(&self, name: &str) -> Result<bool> {
        validate_owned_auth_name(name)?;
        self.remove_raw(name)

View on GitHub (pinned to 73e0f67d83)