Skip to content

[Bug]: two divergent is_binary detectors in forge_fs — fs_search/fs_write vs read_range disagree on same file #3633

Description

@chirag127

Problem

forge_fs ships two different is_binary implementations that are invoked from different code paths, so the same file can be classified as binary by one path and text by the other.

Cite

  • crates/forge_fs/src/binary_detection.rs:32 — pub is_binary(path): BOM + zero-byte heuristic over first 512 bytes.
  • crates/forge_fs/src/is_binary.rs:23ForgeFS::is_binary(&mut File): infer crate MIME sniff over first 8192 bytes; infer::get() == None returns is_text=true ("Assume text if type can't be determined").
  • crates/forge_fs/src/lib.rs:20 re-exports only the BOM variant as forge_fs::is_binary.
  • crates/forge_fs/src/meta.rs:12 ForgeFS::is_binary_file → BOM detector.
  • crates/forge_infra/src/fs_meta.rs:14 FileInfoInfra::is_binaryis_binary_file → BOM detector. Used by fs_search.rs:218,257,456, fs_write.rs, plan_create.rs, image_read.rs.
  • crates/forge_fs/src/read_range.rs:51 read_range_utf8ForgeFS::is_binary (infer variant).

Steps

  1. Create a file with a UTF-8 text prefix and a stray 0x00 in the first 512 bytes (e.g. printf 'KEY=value\0trailing text' > /tmp/mixed.txt).
  2. fs_search / any FileInfoInfra::is_binary caller: BOM detector sees the zero byte, returns true → file is skipped as binary.
  3. read_range_utf8 on same file: infer::get() returns None for unknown bytes, is_text=true, read proceeds and returns lossy UTF-8.

Expected

One canonical detector. All call sites route through the same function so classification is consistent.

Actual

Same file is skipped-as-binary by fs_search but readable via read_range_utf8; user sees content in read responses that search claims doesn't exist.

Environment

  • Repo: tailcallhq/forgecode@main (HEAD 2026-07-03)
  • Cargo.toml: rust-version = "1.94", edition = "2024", infer = "0.19.0"

Thanks for maintaining tailcallhq/forgecode!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions