{"record":{"id":"e3f38fe4c01ad0cd","repo":"Hmbown/CodeWhale","slug":"is-not-valid-utf-8","errorCode":null,"errorMessage":"{} is not valid UTF-8","messagePattern":"(.+?) is not valid UTF-8","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":2482,"sourceCode":"            Err(error) if error.kind() == io::ErrorKind::NotFound => {}\n            Err(error) => {\n                return Err(anyhow!(\n                    \"could not inspect {}: {error}\",\n                    candidate.display()\n                ));\n            }\n        }\n        if ancestor == boundary {\n            break;\n        }\n    }\n    Ok(None)\n}\n\nfn load_workspace_dotenv_credentials_from_path(path: &Path) -> Result<WorkspaceDotenvReport> {\n    let contents = read_stable_workspace_dotenv(path)?;\n    let text = std::str::from_utf8(&contents)\n        .map_err(|_| anyhow!(\"{} is not valid UTF-8\", path.display()))?;\n    if dotenv_has_variable_expansion(text) {\n        bail!(\n            \"{} uses variable expansion; workspace .env values must be literal to prevent ambient-secret substitution\",\n            path.display()\n        );\n    }\n\n    let mut report = WorkspaceDotenvReport {\n        path: path.to_path_buf(),\n        ..WorkspaceDotenvReport::default()\n    };\n    let entries = dotenvy::from_read_iter(std::io::Cursor::new(contents))\n        .collect::<std::result::Result<Vec<_>, _>>()\n        .map_err(|_| anyhow!(\"{} could not be parsed safely\", path.display()))?;\n    for entry in entries {\n        let (key, value) = entry;\n        if !is_workspace_dotenv_credential_key(&key) {\n            report.ignored.insert(key);","sourceCodeStart":2464,"sourceCodeEnd":2500,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/lib.rs#L2464-L2500","documentation":"After the secure-open and link checks pass, Codewhale decodes the workspace .env bytes with std::str::from_utf8. A single invalid byte anywhere makes the entire file fail with '{path} is not valid UTF-8'. dotenvy needs text input, so this gate runs before any parsing or credential extraction; no partial load happens.","triggerScenarios":"A .env saved as UTF-16 (typical after Windows PowerShell 5 Out-File/Set-Content defaults), Latin-1 or CP1252 with non-ASCII bytes, a binary blob pasted into the file, or encrypted secrets written as raw bytes.","commonSituations":"Windows PowerShell 5 wrote the file as UTF-16; an editor saved with a legacy codepage; a password manager exported secrets in a non-UTF-8 encoding.","solutions":["Re-save the file as UTF-8 without BOM (vim :set fenc=utf8; PowerShell Set-Content -Encoding utf8NoBOM)","Run file .env — the output should say 'UTF-8 Unicode text' or 'ASCII text'","Replace non-ASCII bytes inside tokens or values with ASCII-safe equivalents","If the file came from another tool, regenerate or convert it: iconv -f UTF-16 -t UTF-8 .env"],"exampleFix":"# before (Windows PowerShell 5 wrote UTF-16)\nSet-Content .env \"OPENAI_API_KEY=sk-...\"\n\n# after\nSet-Content -Encoding utf8NoBOM .env \"OPENAI_API_KEY=sk-...\"","handlingStrategy":"validation","validationCode":"let bytes = std::fs::read(\".env\")?;\nif std::str::from_utf8(&bytes).is_err() {\n    eprintln!(\".env is not UTF-8; re-save it as UTF-8 without BOM before running codewhale\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Save .env files as UTF-8 without BOM","On Windows PowerShell 5, always pass -Encoding utf8 or utf8NoBOM explicitly","Run file .env after generating it from another tool to confirm the encoding"],"tags":["rust","env","encoding","utf-8","dotenv"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}