datawhalechina/hello-agents · warning · PatchApplyError

Too many files in patch: {len(set(touched_files))} > {self.m

Error message

Too many files in patch: {len(set(touched_files))} > {self.max_files}

What it means

PatchApplyError raised by ApplyPatchExecutor when the number of distinct files touched by add/update/delete operations exceeds the executor's configured max_files limit. This is a guardrail against overly broad agent-generated patches; parsing succeeds but execution is refused before any file is modified.

Source

Thrown at Co-creation-projects/YYHDBL-HelloCodeAgentCli/code_agent/executors/apply_patch_executor.py:116

        3. 创建备份目录
        4. 逐个执行操作 (先备份再修改)
        
        参数:
            patch_text: 符合 Codex 风格的补丁文本,以 *** Begin Patch 开始,*** End Patch 结束
            
        返回:
            ApplyResult: 包含被修改文件和备份文件信息的结果对象
            
        异常:
            PatchApplyError: 当补丁不符合格式、超出限制或应用失败时抛出
        """
        # 解析补丁文本,提取操作列表
        ops = self._parse_patch(patch_text)
        
        # 统计受影响的文件数量,检查是否超过限制
        touched_files = [op[1] for op in ops if op[0] in {"add", "update", "delete"}]
        if len(set(touched_files)) > self.max_files:
            raise PatchApplyError(f"Too many files in patch: {len(set(touched_files))} > {self.max_files}")

        # 估算补丁修改的总行数,检查是否超过限制
        total_changed = self._estimate_changed_lines(ops)
        if total_changed > self.max_total_changed_lines:
            raise PatchApplyError(f"Patch too large: {total_changed} changed lines > {self.max_total_changed_lines}")

        # 创建本次补丁应用的专属备份目录(时间戳命名)
        backup_run_dir = self.backups_dir / datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_run_dir.mkdir(parents=True, exist_ok=True)

        # 初始化结果收集变量
        files_changed: List[str] = []  # 记录被修改的文件路径
        backups: List[str] = []  # 记录创建的备份文件路径

        # 遍历所有解析出的操作,逐个执行
        for kind, rel_path, payload in ops:
            # 安全检查:确保路径在仓库内,防止路径遍历攻击
            target = self._safe_path(rel_path)

View on GitHub (pinned to 606a07d341)

Solutions

  1. Split the patch into multiple smaller apply calls, each under the file limit.
  2. Reconsider scope: a focused patch per logical change is the intended usage.
  3. If the broad change is genuinely required, raise executor max_files in its constructor/config — but treat this as a policy decision, not a quick fix.
  4. Check the error message: it reports actual vs allowed counts.

Example fix

# before
executor.apply(big_patch)  # touches 12 files, max_files=10 -> PatchApplyError

# after
for chunk in split_patch_by_file(big_patch, max_files=executor.max_files):
    result = executor.apply(chunk)
Defensive patterns

Strategy: validation

Validate before calling

ops = parse_patch(patch_text)
touched = {op.path for op in ops if op.kind in {"add", "update", "delete"}}
assert len(touched) <= executor.max_files, f"split patch: {len(touched)} > {executor.max_files}"

Try / catch

try:
    result = executor.apply(patch_text)
except PatchApplyError as e:
    if str(e).startswith("Too many files"):
        for chunk in split_patch_by_file(patch_text, executor.max_files):
            executor.apply(chunk)
    else:
        raise

Prevention

When it happens

Trigger: Submitting a patch whose set of '*** Add File'/'*** Update File'/'*** Delete File' targets exceeds max_files (e.g. 10 files with a limit of 5). Fails atomically — no backups or writes happen.

Common situations: LLM agent attempting a large refactor in one patch; limit lowered in config after workflows were built; batch scripts generating multi-file patches without chunking.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/9ab94adbe6758ed1. Report an issue: GitHub.