{"record":{"id":"8c6382014fb266d4","repo":"datawhalechina/hello-agents","slug":"unknown-op-kind-kind","errorCode":null,"errorMessage":"Unknown op kind: {kind}","messagePattern":"Unknown op kind: (.+?)","errorType":"exception","errorClass":"PatchApplyError","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/YYHDBL-HelloCodeAgentCli/code_agent/executors/apply_patch_executor.py","lineNumber":180,"sourceCode":"            elif kind == \"update\":\n                # 更新文件操作\n                if not target.exists():\n                    raise PatchApplyError(f\"Update File target missing: {rel_path}\")\n                # 读取原始文件内容（保留换行符）\n                original = target.read_text(encoding=\"utf-8\").splitlines(keepends=True)\n                # 修改前先备份文件\n                b = self._backup_file(target, backup_run_dir)\n                backups.append(str(b))\n                # 应用更新补丁内容\n                updated = self._apply_update_payload(original, payload, rel_path)\n                # 原子写入更新后的内容\n                self._atomic_write(target, \"\".join(updated))\n                # 记录变更\n                files_changed.append(rel_path)\n                \n            else:\n                # 未知操作类型\n                raise PatchApplyError(f\"Unknown op kind: {kind}\")\n\n        # 返回最终的应用结果\n        return ApplyResult(files_changed=files_changed, backups=backups)\n\n    def _safe_path(self, rel_path: str) -> Path:\n        \"\"\"\n        验证路径安全性，防止路径遍历攻击 (Path Traversal)。\n        确保目标路径在 repo_root 目录下，防止访问仓库外的文件。\n        \n        参数:\n            rel_path: 相对路径字符串\n            \n        返回:\n            Path: 安全的绝对路径对象\n            \n        异常:\n            PatchApplyError: 当路径是绝对路径、包含特殊字符或试图访问仓库外时抛出\n        \"\"\"","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/YYHDBL-HelloCodeAgentCli/code_agent/executors/apply_patch_executor.py#L162-L198","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nelse:\n    raise PatchApplyError(f\"Unknown op kind: {kind}\")\n\n# after (support delete ops emitted by the parser)\nelif kind == \"delete\":\n    target = self._safe_path(rel_path)\n    self._enforce_suffix(target)\n    b = self._backup_file(target, backup_run_dir)\n    backups.append(str(b))\n    target.unlink(missing_ok=True)\n    files_changed.append(rel_path)\nelse:\n    raise PatchApplyError(f\"Unknown op kind: {kind}\")","handlingStrategy":"validation","validationCode":"SUPPORTED = {'add', 'update', 'delete'}\nops = executor._parse_patch(patch_text)  # or your parser\nbad = [k for k, _, _ in ops if k not in SUPPORTED]\nif bad:\n    raise ValueError(f'patch contains unsupported op kinds: {bad}')","typeGuard":null,"tryCatchPattern":"try:\n    result = executor.apply(patch_text)\nexcept PatchApplyError as e:\n    if 'Unknown op kind' in str(e):\n        # strip unsupported sections and regenerate the patch\n        ...\n    raise","preventionTips":["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."],"tags":["patch","apply-patch","validation","agent-cli"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}