datawhalechina/hello-agents · error · PatchApplyError

Patch must start with '*** Begin Patch'

Error message

Patch must start with '*** Begin Patch'

What it means

Raised by the patch parser when, after lenient preprocessing (skipping leading blank lines and ```/```patch/```diff/```text fences, and scanning forward for the marker), the text still does not begin with a line reading exactly '*** Begin Patch'. The parser tolerates LLM fencing but requires the canonical codestyle-patch header somewhere at the start.

Source

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

            
        返回:
            List[Tuple[str, str, str]]: 操作列表,每个操作包含(操作类型, 路径, 内容)
            
        异常:
            PatchApplyError: 当补丁格式不符合要求时抛出
        """
        lines = text.splitlines()
        # 宽容处理:跳过前置空行/代码块围栏,找到真正的开头
        while lines and lines[0].strip() in {"", "```", "```patch", "```diff", "```text"}:
            lines = lines[1:]
        # 如果仍未以标头开头,尝试向下寻找标头并截取
        if lines and lines[0].strip() != "*** Begin Patch":
            for idx, l in enumerate(lines):
                if l.strip() == "*** Begin Patch":
                    lines = lines[idx:]
                    break
        if not lines or lines[0].strip() != "*** Begin Patch":
            raise PatchApplyError("Patch must start with '*** Begin Patch'")
        # 同样跳过结尾的围栏/空行
        while lines and lines[-1].strip() in {"", "```"}:
            lines = lines[:-1]
        if not lines or lines[-1].strip() != "*** End Patch":
            # 如果末尾未对齐,尝试在中间找到最后一个 End 标记
            for idx in range(len(lines) - 1, -1, -1):
                if lines[idx].strip() == "*** End Patch":
                    lines = lines[: idx + 1]
                    break
        if not lines or lines[-1].strip() != "*** End Patch":
            raise PatchApplyError("Patch must end with '*** End Patch'")

        ops: List[Tuple[str, str, str]] = []
        i = 1
        while i < len(lines) - 1:
            line = lines[i]
            if line.startswith("*** Add File: "):
                path = line[len("*** Add File: ") :].strip()

View on GitHub (pinned to 606a07d341)

Solutions

  1. Ensure the patch text literally contains '*** Begin Patch' as its own line and '*** End Patch' at the end.
  2. If the model returned a unified diff, convert it or re-prompt with the required format in the system prompt.
  3. Strip surrounding prose/fences before calling apply; the parser helps but cannot invent the header.

Example fix

# before
patch_text = '''```diff
--- a/foo.py
+++ b/foo.py
```'''  # unified diff -> error

# after
patch_text = '''*** Begin Patch
*** Update File: foo.py
@@
 context
-old
+new
*** End Patch'''
Defensive patterns

Strategy: validation

Validate before calling

def has_begin_marker(text: str) -> bool:
    return any(l.strip() == '*** Begin Patch' for l in text.splitlines())

if not has_begin_marker(patch_text):
    raise ValueError('patch lacks *** Begin Patch; regenerate in codestyle-patch format')

Type guard

def looks_like_patch(text: str) -> bool:
    lines = [l.strip() for l in text.splitlines()]
    return '*** Begin Patch' in lines and '*** End Patch' in lines

Try / catch

try:
    executor.apply(patch_text)
except PatchApplyError as e:
    if 'must start with' in str(e):
        patch_text = extract_between_markers(patch_text)  # or re-prompt the model
        executor.apply(patch_text)

Prevention

When it happens

Trigger: Passing raw model output that contains no '*** Begin Patch' line at all; a header with typos ('** Begin Patch', '*** begin patch'); nested code fences that make the scan miss the marker; an empty string.

Common situations: LLM omits the fence format and emits a unified diff instead; chat responses with the patch buried after prose (the forward scan only finds the marker if it exists, but leading non-fence prose lines before the marker are skipped only by the scan — prose before a valid marker is handled, missing markers are not); string concatenation dropping the first line.

Related errors


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