快速结论:在 FilesystemFileSearchMiddleware.grep_search 中启用 use_ripgrep=True 时,只要 ripgrep 对模式报错(例如使用了它不支持的 look-ahead),或运行时忽略 max_file_size_mb,就会出现“明明有匹配却返回 No matches found”或“超大文件仍被返回”的现象。优先排查 ripgrep 的退出码处理与 --max-filesize 是否下发。
适用环境:Issue 已确认工具为 LangChain(langchain 包),环境为 Linux,ripgrep 13.0.0 与 14.1.0,langchain 1.4.3(master commit 57236d55d9)。复现脚本为纯 Python,依赖 langchain.agents.middleware.file_search.FilesystemFileSearchMiddleware,路径与 rg. --json 的控制台调用。Issue 未声明 Python 与 CUDA/显卡信息。
最快修复方案:暂无已在发布版本中确认的一步修复方案。Issue 讨论中提交者本地验证的改法是将 ripgrep 退出码非 0/1 视为失败并返回 None,从而触发既有的 Python fallback;同时给 rg 命令补上 --max-filesize,让 max_file_size_mb 在 ripgrep 路径生效。该改动在提交者环境(ripgrep 14.1.0)本地验证通过,但 PR 因未分配作者被自动关闭,需维护者分配后重新提交才能合入。
注意事项:以上修复方案尚未合并到稳定版本,属于可优先尝试的本地改动思路。若你选择自己打补丁,请保留 FileNotFoundError、TimeoutExpired 等既有分支行为;是否把 ripgrep 的 stderr 直接透传给模型,是维护者层面的设计问题,Issue 中未定论。
问题场景
在 LangChain 的 agent middleware 中使用 FilesystemFileSearchMiddleware.grep_search 进行文件内容检索时触发。该工具文档声称:有 ripgrep 就用 ripgrep,否则回退到纯 Python 搜索。用户的实际场景有两种:
- 使用 Python 正则引擎接受、但 ripgrep 不支持的语法(如 look-ahead
foo(?=bar)),期望得到与 Python fallback 一致的结果。 - 设置了
max_file_size_mb限制,期望超过阈值的文件在两条搜索路径下都被跳过。
两种场景在 use_ripgrep=True 与 use_ripgrep=False 下结果不一致,说明两条路径的行为没有对齐。
报错原文
use_ripgrep=True: 'No matches found'
use_ripgrep=False: '/a.txt:1:foobar'
rg returncode: 2 | stderr: error: look-around, including look-ahead and look-behind, is not supported
max_file_size_mb=10 use_ripgrep=True: /big.txt
max_file_size_mb=10 use_ripgrep=False: No matches found
原因分析
可能原因有两个,均与 _ripgrep_search 的实现细节有关:
- ripgrep 出错被吞掉。
subprocess.run使用了check=False,ripgrep 因不支持 look-around 退出码为 2,stdout 为空,于是_ripgrep_search返回空结果而不是None。调用方的回退逻辑只在结果为None时才执行 Python 搜索,因此 fallback 永远不会触发,最终返回与“真的没有匹配”相同的字符串No matches found。 - 文件大小限制未下发。
max_file_size_mb只在 Python fallback 路径上被强制检查,ripgrep 命令行没有加入--max-filesize,所以 11 MB 文件在max_file_size_mb=10时仍被 ripgrep 返回。
Issue 讨论还提出一个设计层面的疑问:ripgrep 报错时,是应当回退到 Python 搜索,还是把 stderr 返回给模型让它改写模式。讨论中的结论倾向于回退,因为方法已有 fallback 文档承诺,且 FileNotFoundError/TimeoutExpired 分支的处理方式也是回退。
环境排查
- 确认 LangChain 版本,Issue 复现基于 langchain 1.4.3(master commit
57236d55d9)。 - 确认
ripgrep是否在 PATH 中,以及版本号:Issue 中 13.0.0 和 14.1.0 均可复现。 - 确认操作系统:Linux。
- 确认
FilesystemFileSearchMiddleware的构造参数:use_ripgrep、max_file_size_mb、root_path。 - 确认 Python 环境中能否导入
langchain.agents.middleware.file_search;Issue 中曾出现测试环境缺少blockbuster导致 pytest 无法收集相关文件的情况。 - Issue 未涉及 CUDA、PyTorch、显卡或模型版本,无需排查这些项。
解决步骤
- 先在本地复现两类不一致:用
foo(?=bar)分别以use_ripgrep=True和False调用grep_search;再构造一个超过max_file_size_mb的文件,观察两条路径的差异。 - 手动执行
rg --json -- "foo(?=bar)" <dir>,确认返回码是否为 2 且 stderr 提示 look-around 不受支持,以证实“ripgrep 报错被吞”的判断。 - 定位
libs/langchain_v1/langchain/agents/middleware/file_search.py中_ripgrep_search的退出码处理位置(Issue 讨论提到约在:314与:347),将退出码非 0(匹配)且非 1(无匹配)的情况改为返回None,让调用方已有的 Python fallback 生效。 - 在同一命令构造处,将
max_file_size_bytes转换为--max-filesize参数传给rg,使文件大小限制在 ripgrep 路径同样生效。 - 补充回归测试:覆盖 ripgrep 退出码 2 时回退到 Python 搜索、
_ripgrep_search在错误时返回None、命令中包含--max-filesize三种情况。Issue 中提到这三条测试在原始代码上失败、打补丁后通过,整个 file-search 测试套件 45 项全绿。 - 提交前运行 ruff 与 mypy strict 检查。如果所在环境缺少
blockbuster导致 pytest 无法收集测试文件,需要先补齐该依赖或换用配置完整的解释器。
验证方法
重新运行 Issue 中的复现脚本,检查两点:use_ripgrep=True 对 foo(?=bar) 返回结果应与 use_ripgrep=False 一致(即 /a.txt:1:foobar),而不再是 No matches found;在 max_file_size_mb=10 下,11 MB 的 big.txt 在两条路径上都应被跳过。若能运行测试,确认新增的三条回归用例与整个 file-search 套件(45 项)全部通过。由于该修复尚未合入发布版本,验证仅在本地补丁或合并后的分支上有意义。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


![[RFC] Add `modeling_xxx_fusion.py` to support kernel fusion](https://www.chat-gpts.plus/wp-content/uploads/2026/10/13845-d26e81d5-768x403.jpg)