Grep tool silently returns zero results for invalid `type` (e.g. `tsx`) instead of surfacing rg's validation error

Resolved 💬 3 comments Opened May 3, 2026 by 1e1f Closed May 6, 2026

Summary

The Grep tool accepts a type argument that is forwarded to ripgrep's --type. When the value is not a registered rg type (e.g. "tsx", which is not a built-in — .tsx files belong to ts), ripgrep exits non-zero with unrecognized file type: tsx. The Grep tool wrapper appears to swallow that error and translate it into numFiles: 0 / "No files found" rather than reporting the validation failure.

The model trusts the empty result and stops investigating, causing false-negative searches that send agents down phantom-bug rabbit holes.

Repro

In any project containing .tsx files with a known pattern:

echo '{"type":"user","message":{"role":"user","content":[{"type":"text","text":"Use the Grep tool with these EXACT params: pattern=\"Gauges\", path=\".\", type=\"tsx\", output_mode=\"files_with_matches\". Just call it once."}]},"parent_tool_use_id":null}' \
  | claude --print --input-format stream-json --output-format stream-json --model claude-sonnet-4-6

Observed in the tool_use_result frame:

{"mode":"files_with_matches","filenames":[],"numFiles":0}

The same call with type removed (or type: "ts", which is the correct rg type and covers .ts + .tsx) returns the expected matches.

For comparison, running rg directly:

$ rg --type tsx Gauges
rg: unrecognized file type: tsx
$ echo $?
2

Expected

Either:

  1. The tool surfaces the rg validation error in the result ({"error": "unrecognized file type: tsx — try \"ts\" or use the glob field"}), so the model knows to retry, or
  2. The tool normalizes common aliases (tsx → ts, jsx → js) before calling rg.

Silently returning zero matches is the worst of both worlds — it looks like a clean answer.

Impact

Hit this debugging an agent harness. The agent passed type: "tsx" (a very natural choice given how prevalent TypeScript JSX is), got "No matches found," concluded the symbol didn't exist, and looped 25 tool calls trying to figure out a phantom missing-code bug. Models default to tsx because the file extension and the type name are intuitively the same.

Workaround

Until then, prompt agents to use type: "ts" (covers both extensions) or glob: "**/*.tsx".

Environment

  • claude-code 2.1.126
  • macOS 25.4.0 / arm64
  • Reproduced both directly from a shell and via a stream-json wrapper subprocess.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗