Skip to content

fix(read_file): treat lone trailing U+FFFD as UTF-8 truncation artifact, not binary - #81834

Closed
VIVAAN-DHAWAN wants to merge 1 commit into
NousResearch:mainfrom
VIVAAN-DHAWAN:fix-readfile-binary-false-positive
Closed

VIVAAN-DHAWAN wants to merge 1 commit into
NousResearch:mainfrom
VIVAAN-DHAWAN:fix-readfile-binary-false-positive

Conversation

@VIVAAN-DHAWAN

Copy link
Copy Markdown
Contributor

Fixes #81480

read_file samples file contents via head -c 1000 and decodes with errors="replace". When a multibyte UTF-8 character straddles the 1000-byte sample boundary, the truncation produces a single trailing U+FFFD replacement character, which _is_likely_binary then treats as a binary-content signal — so valid UTF-8 text files are flagged isBinary: true.

This fixes the whole class, not just the one site: a lone trailing U+FFFD is a sampling artifact and no longer implies binary; multiple U+FFFDs, or a trailing U+FFFD accompanied by other garbage, are still treated as binary.

Changes

  • tools/file_operations.py::_is_likely_binary: only treat U+FFFD as a binary signal when it appears more than once or is not the trailing character.
  • tests/tools/test_file_operations_edge_cases.py::TestIsLikelyBinary: added coverage for the three cases (single trailing artifact → not binary; multiple scattered replacements → binary; trailing replacement + other garbage → binary).

Verification

  • tests/tools/test_file_operations_edge_cases.py — 24 passed.

…ct, not binary

read_file samples via `head -c 1000`, which truncates at a byte boundary.
When that boundary splits a multi-byte UTF-8 character, the terminal env's
errors=replace decode produces exactly one *trailing* U+FFFD — which the
binary detector flagged as binary, blocking reading of valid UTF-8 text
files like Portuguese .md docs (NousResearch#81480).

Genuine binary data yields many scattered replacement chars, so only a
sample with >1 U+FFFD, or one that ends without a trailing U+FFFD, is
treated as binary. A lone trailing replacement is now read as text.

Adds regression tests for the sampling-artifact case and keeps the
scattered-replacement binary case guarded.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/tools Tool registry, model_tools, toolsets tool/file File tools (read, write, patch, search) needs-decision Awaiting maintainer decision before any implementation labels Aug 8, 2026
@teknium1

teknium1 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Closing — superseded by #81961, which fixed this bug class (1000-byte sample cutting a multibyte char → binary false positive) at the byte layer across read_file, patch, and search_files, with regression tests for truncated-CJK/BOM/UTF-16/NUL cases. ~24 PRs raced on this one; earliest diagnosis credit to @webtecnica (#76924), merged implementation from @ayushnangia (#80440). Thanks for jumping on it.

@teknium1 teknium1 closed this Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tools Tool registry, model_tools, toolsets needs-decision Awaiting maintainer decision before any implementation P2 Medium — degraded but workaround exists tool/file File tools (read, write, patch, search) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(read_file): valid UTF-8 .md file flagged as binary (false positive)

3 participants