{"record":{"id":"2f77ac2a8afba550","repo":"Hmbown/CodeWhale","slug":"codewhale-owned-xai-oauth-file-is-not-valid-utf","errorCode":null,"errorMessage":"Codewhale-owned xAI OAuth file {} is not valid UTF-8","messagePattern":"Codewhale-owned xAI OAuth file (.+?) is not valid UTF-8","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/xai_credentials.rs","lineNumber":254,"sourceCode":"        let mut bytes = Vec::with_capacity(metadata.len() as usize);\n        (&mut file)\n            .take(XAI_OAUTH_FILE_LIMIT + 1)\n            .read_to_end(&mut bytes)\n            .with_context(|| {\n                format!(\n                    \"reading Codewhale-owned xAI OAuth file {}\",\n                    crate::quote_os_path(&self.directory.join(name))\n                )\n            })?;\n        if bytes.len() as u64 > XAI_OAUTH_FILE_LIMIT {\n            bail!(\n                \"Codewhale-owned xAI OAuth file {} exceeds the {} byte limit\",\n                crate::quote_os_path(&self.directory.join(name)),\n                XAI_OAUTH_FILE_LIMIT\n            );\n        }\n        String::from_utf8(bytes).map(Some).map_err(|_| {\n            anyhow::anyhow!(\n                \"Codewhale-owned xAI OAuth file {} is not valid UTF-8\",\n                crate::quote_os_path(&self.directory.join(name))\n            )\n        })\n    }\n\n    pub fn write(&self, name: &str, bytes: &[u8], allow_replace: bool) -> Result<()> {\n        validate_owned_auth_name(name)?;\n        anyhow::ensure!(\n            bytes.len() as u64 <= XAI_OAUTH_FILE_LIMIT,\n            \"refusing oversized xAI OAuth credential payload\"\n        );\n        self.write_owned_file(name, bytes, allow_replace)\n    }\n\n    pub fn remove(&self, name: &str) -> Result<bool> {\n        validate_owned_auth_name(name)?;\n        self.remove_raw(name)","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/config/src/xai_credentials.rs#L236-L272","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Delete the corrupt file and re-authenticate so the store rewrites it (e.g. rm the path, then run the xAI login/logout flow).","Check the file with `file`/`xxd` to confirm it is non-text, and restore a known-good backup if one exists.","Verify no sync tool or editor is touching ~/.codewhale credentials; exclude the directory from syncing.","Ensure disk health / fsck if corruption is recurring."],"exampleFix":"// before (corrupt file fails)\nlet token = store.read_to_string(\"xai.oauth.v1.json\")?;\n// after (recover by re-creating)\nif store.read_to_string(\"xai.oauth.v1.json\").is_err() {\n    store.write(\"xai.oauth.v1.json\", fresh_token_bytes, true)?;\n}","handlingStrategy":"try-catch","validationCode":"let bytes = std::fs::read(&path)?;\nanyhow::ensure!(std::str::from_utf8(&bytes).is_ok(), \"credential file is not UTF-8; re-authenticate\");","typeGuard":"fn is_utf8_file(path: &Path) -> bool {\n    std::fs::read(path).map(|b| std::str::from_utf8(&b).is_ok()).unwrap_or(false)\n}","tryCatchPattern":"match store.read_to_string(name) {\n    Ok(token) => token,\n    Err(e) if e.to_string().contains(\"not valid UTF-8\") => {\n        // delete and re-authenticate\n        let _ = std::fs::remove_file(path);\n        reauthenticate()?;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Exclude the credentials directory from file-sync and editor tooling","Let the store perform all writes; never hand-edit token files","Back up known-good token files if you must automate refreshes","Monitor for repeated corruption as a disk-health signal"],"tags":["utf-8","credentials","file-read","corruption"],"backgroundTag":"file-read-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}