datawhalechina/hello-agents · error · PatchApplyError

Unknown op kind: {kind}

Error message

Unknown op kind: {kind}

What it means

Raised by ApplyPatchExecutor's apply loop when an op parsed from the patch text has a kind that is neither 'add' nor 'update' (nor any other kind handled before the else). It signals a mismatch between the patch parser (_parse_patch) output and the ops the apply loop supports, i.e. internal format drift or a hand-crafted patch with an unrecognized '*** ' section header that the parser still accepted.

Source

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

            elif kind == "update":
                # 更新文件操作
                if not target.exists():
                    raise PatchApplyError(f"Update File target missing: {rel_path}")
                # 读取原始文件内容(保留换行符)
                original = target.read_text(encoding="utf-8").splitlines(keepends=True)
                # 修改前先备份文件
                b = self._backup_file(target, backup_run_dir)
                backups.append(str(b))
                # 应用更新补丁内容
                updated = self._apply_update_payload(original, payload, rel_path)
                # 原子写入更新后的内容
                self._atomic_write(target, "".join(updated))
                # 记录变更
                files_changed.append(rel_path)
                
            else:
                # 未知操作类型
                raise PatchApplyError(f"Unknown op kind: {kind}")

        # 返回最终的应用结果
        return ApplyResult(files_changed=files_changed, backups=backups)

    def _safe_path(self, rel_path: str) -> Path:
        """
        验证路径安全性,防止路径遍历攻击 (Path Traversal)。
        确保目标路径在 repo_root 目录下,防止访问仓库外的文件。
        
        参数:
            rel_path: 相对路径字符串
            
        返回:
            Path: 安全的绝对路径对象
            
        异常:
            PatchApplyError: 当路径是绝对路径、包含特殊字符或试图访问仓库外时抛出
        """

View on GitHub (pinned to 606a07d341)

Solutions

  1. Inspect the parsed ops (log [(kind, path) for kind, path, _ in ops]) right before apply to see which kind is unrecognized.
  2. If the patch uses '*** Delete File: ', add a matching branch in the apply loop (or remove the section from the patch).
  3. Regenerate the patch so it only contains '*** Add File: ' and '*** Update File: ' sections.
  4. If you control both sides, validate kinds in _parse_patch and fail there with a clearer message.

Example fix

# before
else:
    raise PatchApplyError(f"Unknown op kind: {kind}")

# after (support delete ops emitted by the parser)
elif kind == "delete":
    target = self._safe_path(rel_path)
    self._enforce_suffix(target)
    b = self._backup_file(target, backup_run_dir)
    backups.append(str(b))
    target.unlink(missing_ok=True)
    files_changed.append(rel_path)
else:
    raise PatchApplyError(f"Unknown op kind: {kind}")
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED = {'add', 'update', 'delete'}
ops = executor._parse_patch(patch_text)  # or your parser
bad = [k for k, _, _ in ops if k not in SUPPORTED]
if bad:
    raise ValueError(f'patch contains unsupported op kinds: {bad}')

Try / catch

try:
    result = executor.apply(patch_text)
except PatchApplyError as e:
    if 'Unknown op kind' in str(e):
        # strip unsupported sections and regenerate the patch
        ...
    raise

Prevention

When it happens

Trigger: Calling apply() with patch text whose ops list contains a kind string outside the supported set — e.g. a patch containing a '*** Delete File: ' section if the parser emits a 'delete' kind but the apply loop never handles it, or a parser bug that produces an empty/None kind.

Common situations: Extending the patch format with new op types (delete, rename, move) in the parser but forgetting the apply branch; model-generated patches using a nonstandard '*** ' directive; version skew between an old patch blob and a newer executor.

Related errors


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