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
- Inspect the parsed ops (log [(kind, path) for kind, path, _ in ops]) right before apply to see which kind is unrecognized.
- If the patch uses '*** Delete File: ', add a matching branch in the apply loop (or remove the section from the patch).
- Regenerate the patch so it only contains '*** Add File: ' and '*** Update File: ' sections.
- 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
- Keep the parser's emitted op kinds and the apply loop's branches in one reviewed change set.
- Add a unit test asserting every kind the parser can emit is handled in apply().
- Constrain the model's system prompt to Add/Update/Delete sections only.
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
- Disallowed file suffix for write: {target.suffix}
- Unexpected patch line: {line}
- Absolute paths are not allowed: {rel_path}
- Path escapes repo_root: {rel_path}
- Refusing to modify symlink: {rel_path}
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/8c6382014fb266d4.
Report an issue: GitHub.