{"record":{"id":"2a65737f9ba56c8a","repo":"datawhalechina/hello-agents","slug":"unexpected-patch-line-line","errorCode":null,"errorMessage":"Unexpected patch line: {line}","messagePattern":"Unexpected patch line: (.+?)","errorType":"exception","errorClass":"PatchApplyError","httpStatus":null,"severity":"error","filePath":"Co-creation-projects/YYHDBL-HelloCodeAgentCli/code_agent/executors/apply_patch_executor.py","lineNumber":339,"sourceCode":"                continue\n            if line.startswith(\"*** Delete File: \"):\n                path = line[len(\"*** Delete File: \") :].strip()\n                ops.append((\"delete\", path, \"\"))\n                i += 1\n                continue\n            if line.startswith(\"*** Update File: \"):\n                path = line[len(\"*** Update File: \") :].strip()\n                i += 1\n                buf: List[str] = []\n                while i < len(lines) - 1 and not lines[i].startswith(\"*** \"):\n                    buf.append(lines[i])\n                    i += 1\n                ops.append((\"update\", path, \"\\n\".join(buf)))\n                continue\n            if line.strip() == \"\":\n                i += 1\n                continue\n            raise PatchApplyError(f\"Unexpected patch line: {line}\")\n\n        return ops\n\n    def _estimate_changed_lines(self, ops: List[Tuple[str, str, str]]) -> int:\n        \"\"\"\n        估算补丁操作的总变更行数。\n        用于检查补丁大小是否超过限制。\n        \n        参数:\n            ops: 补丁操作列表\n            \n        返回:\n            int: 估算的总变更行数\n        \"\"\"\n        changed = 0\n        for kind, _, payload in ops:\n            if kind == \"add\":\n                # 添加文件：按行数计算","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/datawhalechina/hello-agents/blob/606a07d341a47be773fab7f4b71177f53f96b2c3/Co-creation-projects/YYHDBL-HelloCodeAgentCli/code_agent/executors/apply_patch_executor.py#L321-L357","documentation":"Raised by the patch parser when a line inside the patch body (between Begin and End) is not an '*** Add File: '/'*** Update File: ' (or Delete) header, not a blank line, and therefore falls through to the catch-all raise. It marks structurally malformed patch bodies the lenient parser cannot reinterpret.","triggerScenarios":"A stray line starting with text other than the recognized sections — e.g. '*** Delete File: foo' if Delete is not handled in this parser path, diff-style '@@ -1,3 +1,4 @@' hunk headers outside an Update body, or prose/comments at top level.","commonSituations":"Mixing unified-dump syntax into the codestyle patch format; models emitting '*** Rename File:' or '*** Delete File:' directives the parser skips; hand-edited patches with section markers of the wrong spelling.","solutions":["Check the exact offending line reported in the message and either remove it or wrap it inside the correct section.","Replace unsupported directives: express a rename as Delete+Add, or add parser support for the directive.","Re-generate the patch strictly in the Add/Update(+Delete-if-supported) grammar."],"exampleFix":"# before\n*** Update File: a.py\n@@ -1,2 +1,2 @@\n-old\n+new\n*** Rename File: a.py -> b.py   <-- unexpected line\n\n# after\n*** Update File: a.py\n@@\n-old\n+new\n(and a separate Add File / Delete File pair for the rename)","handlingStrategy":"validation","validationCode":"KNOWN = ('*** Add File: ', '*** Update File: ', '*** Delete File: ')\nin_section = False\nfor l in patch_text.splitlines():\n    s = l.strip()\n    if s == '*** Begin Patch' or s == '*** End Patch':\n        in_section = (s == '*** Begin Patch'); continue\n    if not in_section: continue\n    if l.startswith('***') and not l.startswith(('+', '-', ' ')):\n        if not l.startswith(KNOWN):\n            raise ValueError(f'unsupported directive: {l!r}')","typeGuard":null,"tryCatchPattern":"try:\n    executor.apply(patch_text)\nexcept PatchApplyError as e:\n    if 'Unexpected patch line' in str(e):\n        offending = str(e).rsplit(':', 1)[-1].strip()\n        patch_text = remove_line(patch_text, offending)  # or re-prompt\n    raise","preventionTips":["Document the exact supported '*** ' directives in the agent prompt.","Express renames as Add+Delete rather than ad-hoc directives.","Lint patch text against the grammar before apply."],"tags":["patch","parsing","validation","apply-patch"],"backgroundTag":null,"analyzedSha":"606a07d341a47be773fab7f4b71177f53f96b2c3","analyzedAt":"2026-08-14T22:57:27.446Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}