AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

FilesystemFileSearchMiddleware Grep_search Swallows Ripgrep Errors And Ignores Max_file_size_mb On Ripgrep Path

The grep_search method in FilesystemFileSearchMiddleware fails to fall back to the Python search when ripgrep exits with an error (return code 2), because _ripgrep_search returns an empty dict instead of None when ripgrep rejects the regex pattern. This leads to a false 'No matches found' response for valid Python regexes like look-ahead/look-behind. Additionally, the max_file_size_mb parameter is not applied to the ripgrep command, causing inconsistent results between ripgrep and Python fallback paths.

highConfidence 85%LangChainAffected V1.4.0

Origin Analysis

In _ripgrep_search, subprocess.run is called with check=False, so non-zero exit codes do not raise CalledProcessError. The method parses stdout (which is empty on error) and returns an empty dict ({}), which is not None. In grep_search, the fallback condition (if results is None) is never triggered, so the Python search is skipped and the function returns 'No matches found'. Furthermore, the ripgrep command is constructed without the --max-filesize argument, so the file size limit is only enforced in the Python fallback.
1. Create a temp directory with a file containing 'foobar'. 2. Instantiate FilesystemFileSearchMiddleware with use_ripgrep=True. 3. Invoke grep_search with pattern 'foo(?=bar)' and output_mode='content'. 4. Observe that it returns 'No matches found' while the Python path (use_ripgrep=False) returns the matching line. 5. Create a file larger than the max_file_size_mb limit. 6. Invoke grep_search with max_file_size_mb=10; note that the ripgrep path returns the file path, while the Python path respects the limit and returns 'No matches found'.

Fixing Code Block

Edge Case Audit

Returning None to trigger the Python fallback may cause performance degradation for large files or complex patterns, as the pure-Python search can be slow and susceptible to ReDoS (see issue #40255). The fallback regex engine may also accept patterns that ripgrep rejects but yield different semantics (e.g., Unicode properties). Adding --max-filesize may cause ripgrep to skip large files silently, which could surprise users if they expect the tool to search all files. In multi-threaded scenarios, the middleware object is shared, but since self.max_file_size_bytes is read-only, there is no race condition. Rollback advice: if this fix introduces unforeseen issues, revert to the original behavior by removing the returncode check and the --max-filesize argument, but consider logging ripgrep's stderr for debugging.

Ecosystem Topology