{"record":{"id":"d6b85db485f0c1c3","repo":"ultraworkers/claw-code","slug":"file-appears-to-be-binary","errorCode":null,"errorMessage":"file appears to be binary","messagePattern":"file appears to be binary","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"rust/crates/runtime/src/file_ops.rs","lineNumber":207,"sourceCode":") -> io::Result<ReadFileOutput> {\n    let absolute_path = normalize_path(path)?;\n\n    // Check file size before reading\n    let metadata = fs::metadata(&absolute_path)?;\n    if metadata.len() > MAX_READ_SIZE {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\n                \"file is too large ({} bytes, max {} bytes)\",\n                metadata.len(),\n                MAX_READ_SIZE\n            ),\n        ));\n    }\n\n    // Detect binary files\n    if is_binary_file(&absolute_path)? {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            \"file appears to be binary\",\n        ));\n    }\n\n    let content = fs::read_to_string(&absolute_path)?;\n    let lines: Vec<&str> = content.lines().collect();\n    let start_index = offset.unwrap_or(0).min(lines.len());\n    let end_index = limit.map_or(lines.len(), |limit| {\n        start_index.saturating_add(limit).min(lines.len())\n    });\n    let selected = lines[start_index..end_index].join(\"\\n\");\n\n    Ok(ReadFileOutput {\n        kind: String::from(\"text\"),\n        file: TextFilePayload {\n            file_path: absolute_path.to_string_lossy().into_owned(),\n            content: selected,","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/ultraworkers/claw-code/blob/08106b0c3771ef5b4a5aa176acccd460e88b7325/rust/crates/runtime/src/file_ops.rs#L189-L225","documentation":"`read_file` (runtime/src/file_ops.rs:207) calls `is_binary_file`, which reads the first 8 KiB and flags the file as binary if it contains any NUL byte (0x00). Rejection is `ErrorKind::InvalidData`. Note that UTF-16-encoded text files contain NUL high bytes and are therefore classified as binary, not just images/executables.","triggerScenarios":"Reading an image, executable, SQLite DB, pickle/parquet file, or any blob with a 0x00 byte in the first 8192 bytes; reading a UTF-16LE/BE text export (every other byte is 0x00).","commonSituations":"Agents wandering into `assets/`, `*.db`, `node_modules` binaries; Windows-origin text files saved as UTF-16; certificate/key DER files.","solutions":["If it really is text in UTF-16, convert first: `iconv -f UTF-16 -t UTF-8 file > file.u8` and read that.","For genuine binaries, use the Bash tool (e.g. `file`, `xxd | head`, `base64`) instead of the Read tool.","Pre-check with the same heuristic (NUL in first 8 KiB) before handing the path to read_file."],"exampleFix":"# before\nRead(file=\"export.csv\")            # file appears to be binary (UTF-16 file)\n\n# after\nBash(command=\"iconv -f UTF-16 -t UTF-8 export.csv > export.utf8.csv\")\nRead(file=\"export.utf8.csv\")","handlingStrategy":"validation","validationCode":"fn looks_binary(p: &Path) -> io::Result<bool> {\n    use std::io::Read;\n    let mut f = std::fs::File::open(p)?;\n    let mut buf = [0u8; 8192];\n    let n = f.read(&mut buf)?;\n    Ok(buf[..n].contains(&0))   // same heuristic as is_binary_file\n}","typeGuard":null,"tryCatchPattern":"match read_file(path, None, None) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData\n        && e.to_string().contains(\"binary\") => { /* iconv UTF-16->UTF-8, or use bash/xxd */ }\n    other => other,\n}","preventionTips":["Convert UTF-16 exports to UTF-8 before reading","Remember NUL in the first 8 KiB is the trigger — includes images, executables, sqlite, DER","Use Bash tool (file/xxd/base64) for anything not plain text"],"tags":["file-ops","read","binary-detection"],"backgroundTag":"binary-file-detection","analyzedSha":"08106b0c3771ef5b4a5aa176acccd460e88b7325","analyzedAt":"2026-08-18T00:29:38.590Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}