datawhalechina/hello-agents · error · PatchApplyError
Unexpected patch line: {line}
Error message
Unexpected patch line: {line} What it means
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.
Source
Thrown at Co-creation-projects/YYHDBL-HelloCodeAgentCli/code_agent/executors/apply_patch_executor.py:339
continue
if line.startswith("*** Delete File: "):
path = line[len("*** Delete File: ") :].strip()
ops.append(("delete", path, ""))
i += 1
continue
if line.startswith("*** Update File: "):
path = line[len("*** Update File: ") :].strip()
i += 1
buf: List[str] = []
while i < len(lines) - 1 and not lines[i].startswith("*** "):
buf.append(lines[i])
i += 1
ops.append(("update", path, "\n".join(buf)))
continue
if line.strip() == "":
i += 1
continue
raise PatchApplyError(f"Unexpected patch line: {line}")
return ops
def _estimate_changed_lines(self, ops: List[Tuple[str, str, str]]) -> int:
"""
估算补丁操作的总变更行数。
用于检查补丁大小是否超过限制。
参数:
ops: 补丁操作列表
返回:
int: 估算的总变更行数
"""
changed = 0
for kind, _, payload in ops:
if kind == "add":
# 添加文件:按行数计算View on GitHub (pinned to 606a07d341)
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.
Example fix
# before *** Update File: a.py @@ -1,2 +1,2 @@ -old +new *** Rename File: a.py -> b.py <-- unexpected line # after *** Update File: a.py @@ -old +new (and a separate Add File / Delete File pair for the rename)
Defensive patterns
Strategy: validation
Validate before calling
KNOWN = ('*** Add File: ', '*** Update File: ', '*** Delete File: ')
in_section = False
for l in patch_text.splitlines():
s = l.strip()
if s == '*** Begin Patch' or s == '*** End Patch':
in_section = (s == '*** Begin Patch'); continue
if not in_section: continue
if l.startswith('***') and not l.startswith(('+', '-', ' ')):
if not l.startswith(KNOWN):
raise ValueError(f'unsupported directive: {l!r}') Try / catch
try:
executor.apply(patch_text)
except PatchApplyError as e:
if 'Unexpected patch line' in str(e):
offending = str(e).rsplit(':', 1)[-1].strip()
patch_text = remove_line(patch_text, offending) # or re-prompt
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Unknown op kind: {kind}
- Disallowed file suffix for write: {target.suffix}
- Patch must start with '*** Begin Patch'
- Absolute paths are not allowed: {rel_path}
- Path escapes repo_root: {rel_path}
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/2a65737f9ba56c8a.
Report an issue: GitHub.