A literal NUL byte in a source file makes ripgrep treat it as binary — and every grep-based sweep silently skips it
A real U+0000 byte inside a string literal makes ripgrep and grep treat the whole source file as binary, so every grep-based sweep silently skips it — replace the raw byte with the escape sequence \u0000, which is identical at runtime but plain text on disk.
Skutečný bajt U+0000 uvnitř řetězcového literálu způsobí, že ripgrep i grep považují celý zdrojový soubor za binárku, takže ho každý grep sweep tiše přeskočí – nahraď syrový bajt escape sekvencí \u0000, která je za běhu identická, ale na disku je to čistý text.
Symptom
grep/rgon one specific.tsfile printsBinary file ... matchesinstead of matching lines.- Bulk find-and-replace sweeps, lint-adjacent scripts, drift checkers and even AI review agents that rely on content search silently skip the file — it becomes a blind spot nobody notices.
- The file compiles and runs perfectly fine; TypeScript and webpack don't care.
Cause
The source file contains a real U+0000 (NUL) character inside a string literal — e.g. a composite map key like:
have[(row.Line || '') + '\u0000' + (row.Title || '')] = true; // fine: escape sequence
written instead with the actual control character between the quotes. This typically happens when an editor,
script, or tool layer decodes an escape sequence while writing the file (you type \u0000, the file gets
the real byte). Ripgrep and GNU grep classify any file containing a NUL byte as binary and stop reporting
line matches for it.
Fix
Replace the raw byte with the escape sequence — identical runtime semantics, plain-text file:
// one-off repair (Node): rewrite NUL bytes as the 6-char escape "\u0000"
const fs = require('fs');
const buf = fs.readFileSync(file);
const esc = Buffer.from('\\u0000', 'utf8');
const out = [];
for (const b of buf) { if (b === 0) { for (const e of esc) out.push(e); } else out.push(b); }
fs.writeFileSync(file, Buffer.from(out));
Prevention / detection
- Never put real control characters into source — always the escape (
'\u0000','\t', …). - After any bulk tool-driven edit, sanity-check:
file src/**/*.ts— a source file reported asdatainstead oftexthas the problem. - If a code audit uses grep-style search, remember such files are invisible to it — read them directly.