Skip to content

fix(grep): surface error on exit code >= 2 instead of false "0 matches"#2465

Merged
KuSh merged 4 commits into
rtk-ai:developfrom
ousamabenyounes:fix/issue-2461
Jun 18, 2026
Merged

fix(grep): surface error on exit code >= 2 instead of false "0 matches"#2465
KuSh merged 4 commits into
rtk-ai:developfrom
ousamabenyounes:fix/issue-2461

Conversation

@ousamabenyounes

Copy link
Copy Markdown
Contributor

Summary

rtk grep prints "0 matches for ''" when the underlying search tool exits with an error code >= 2, even when matches exist and the tool simply failed to run. This is a false negative — LLM agents interpret it as a clean empty result and act on incorrect information.

Root cause: grep_cmd.rs:386-399 handled only the narrow case exit_code == 2 && stderr non-empty. grep/rg convention: exit 1 = no match (normal), exit >= 2 = real error (bad regex, binary crash, missing tool). Any error exit that fell outside the narrow window silently became "0 matches".

Fix: Broadened the gate to exit_code >= 2. All error exits now surface to stderr (prefixed with the exit code for diagnostics) and never print the misleading "0 matches" message. Exit 0 and 1 behavior is unchanged.

Fixes #2461

Test verification (RED → GREEN)

With the fix reverted, the new test fails (RED):

running 1 test
test grep_error_exit_code_no_false_negative ... FAILED

---- grep_error_exit_code_no_false_negative stdout ----
thread 'grep_error_exit_code_no_false_negative' panicked at tests/grep_error_test.rs:50:5:
ERROR exit MUST NOT claim '0 matches' (false negative).
stdout: 0 matches for 'hello'
stderr: 

failures:
    grep_error_exit_code_no_false_negative

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s

With the fix applied, the test passes (GREEN):

running 1 test
test grep_error_exit_code_no_false_negative ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s

Full baseline: 2196 tests pass, 0 fail (2195 existing + 1 new).

🤖 Generated with Claude Code

@hgunduzoglu hgunduzoglu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked this out and tested locally (macOS arm64). The core fix is correct — broadening the gate to exit_code >= 2 matches grep/rg convention, and all three paths behave right:

rg exit meaning before this PR
0 matches grouped output grouped output ✓
1 no match 0 matches 0 matches, exit 1 ✓ (legit empty result preserved)
≥2 real error 0 matches (false negative) grep failed with exit code N on stderr, exit propagated ✓

Verified with a fake rg exiting 2: it now surfaces grep failed with exit code 2 and exits 2 instead of the misleading 0 matches. The new integration test passes here. Nice — this closes a genuine false-negative footgun.

One blocker for CI, though: tests/grep_error_test.rs has an unconditional use std::os::unix::fs::PermissionsExt; (line 6) with no cfg(unix) gate. std::os::unix doesn't exist on Windows, so the integration-test crate will fail to compile on the Windows CI target (RTK ships a Windows build, and cli-testing.md marks cross-platform a 🔴 critical concern). It's the only file under tests/ that touches std::os::unix.

Two small options:

  • Gate the whole file: add #![cfg(unix)] at the top (simplest — the test simulates a broken rg via a chmod'd shell script, which is unix-only anyway), or
  • #[cfg(unix)] on the test fn + #[cfg(unix)] use std::os::unix::....

Either keeps the Windows build green while preserving the unix coverage. Everything else looks good — the fix itself is solid and well-targeted.

@ousamabenyounes

Copy link
Copy Markdown
Contributor Author

Thanks for the review @hgunduzoglu — agreed, that's a real Windows compile break, not a nit. Fixed in 6eaa4a3 with option 1: #![cfg(unix)] at the top of tests/grep_error_test.rs. The test simulates a broken rg via a chmod'd shell script (from_mode / PermissionsExt), so the whole file is unix-only by nature — gating it keeps the Windows CI target green while preserving the unix coverage.

Verified: cross-check against x86_64-pc-windows-gnu now compiles clean (was E0433: could not find unix in os), and the Linux test still passes 1/1.

Comment thread src/cmds/system/grep_cmd.rs Outdated
Comment thread tests/grep_error_test.rs Outdated
@KuSh KuSh self-assigned this Jun 18, 2026
ousamabenyounes and others added 4 commits June 18, 2026 09:34
Exit codes >= 2 signal real errors in grep/rg (bad regex, tool
crash, missing binary). rtk was only checking the narrow case
exit_code == 2 with non-empty stderr, letting any other error
exit masquerade as a clean "0 matches" false negative.

Now any exit code >= 2 surfaces the error to stderr instead of
printing a false zero-match result.

Fixes rtk-ai#2461
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The test simulates a broken `rg` via a chmod'd shell script (from_mode,
PermissionsExt) which is unix-only. The unconditional `use std::os::unix`
broke compilation of the integration-test crate on the Windows CI target.
Gate the whole file so Windows stays green while preserving unix coverage.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wrap the rtk binary path expression per rustfmt to satisfy
`cargo fmt --all -- --check` on CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Address KuSh review on rtk-ai#2465:
- Move the `exit_code >= 2` decision into a pure `is_grep_error_exit`
  function and unit-test it directly (0/1 = normal, >=2 = error),
  instead of faking the rg binary in an integration test.
- Drop the GREP_ERROR_EXIT const; the doc comment on the function
  conveys the grep/rg exit convention.
- Remove tests/grep_error_test.rs (faked binary) in favour of the
  unit test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@KuSh KuSh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks!

@KuSh KuSh merged commit 3572d11 into rtk-ai:develop Jun 18, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

False negative: rtk grep reports '0 matches' on exit code 1 when rg not found

3 participants