datawhalechina/hello-agents · error · PatchApplyError

Update hunk has no context/removals; refusing to apply

Error message

Update hunk has no context/removals; refusing to apply

What it means

Raised while applying an Update File hunk when the 'before' side is empty — the hunk contains only '+' additions and no context (' ') or removal ('-') lines. Pure-insertion hunks are rejected because _find_subsequence has no anchor to locate where the new lines belong, making the write position ambiguous.

Source

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

            PatchApplyError: 当 hunk 格式错误或找不到匹配的上下文时抛出
        """
        before: List[str] = []
        after: List[str] = []
        for l in hunk_lines:
            if not l:
                continue
            tag = l[0]
            text = l[1:] + "\n"
            if tag == " ":
                before.append(text)
                after.append(text)
            elif tag == "-":
                before.append(text)
            elif tag == "+":
                after.append(text)

        if not before:
            raise PatchApplyError("Update hunk has no context/removals; refusing to apply")

        idx = self._find_subsequence(current, before)
        if idx is None:
            context_line = next((b.strip() for b in before if b.strip()), "")
            hint = f"{rel_path}:search:'{context_line[:80]}'"
            raise PatchApplyError("Patch hunk context not found; file changed?", recheck_targets=[hint])

        return current[:idx] + after + current[idx + len(before) :]

    def _find_subsequence(self, haystack: List[str], needle: List[str]) -> Optional[int]:
        """
        在文件内容中查找代码块的起始位置。
        使用简单的 O(N*M) 字符串匹配算法,在 haystack 中查找 needle 的精确匹配。
        
        参数:
            haystack: 文件内容行列表
            needle: 要查找的代码块行列表
            

View on GitHub (pinned to 606a07d341)

Solutions

  1. For new files, use '*** Add File: ' with the full content instead of Update.
  2. For insertions into an existing file, include at least one unchanged context line (prefixed with a single space) above or below the '+' lines.
  3. For end-of-file appends, quote the final existing line(s) as context, then the '+' lines.

Example fix

# before
*** Update File: notes.py
+def new_fn():
+    pass
*** End Patch

# after
*** Update File: notes.py
 def existing_fn():
     pass
+
+def new_fn():
+    pass
Defensive patterns

Strategy: validation

Validate before calling

def hunk_has_anchor(body: str) -> bool:
    lines = [l for l in body.splitlines() if l.strip()]
    return any(not l.startswith('+') for l in lines)  # needs ' ' or '-' lines

Try / catch

try:
    executor.apply(patch_text)
except PatchApplyError as e:
    if 'no context/removals' in str(e):
        # convert to Add File if new, else add surrounding context lines
        patch_text = add_context_lines(patch_text, file_content)
        executor.apply(patch_text)

Prevention

When it happens

Trigger: An Update File body whose every line starts with '+': e.g. trying to append to a file via Update with no surrounding context; models adding a new function but forgetting to include the surrounding context lines.

Common situations: LLM uses Update File where Add File was intended (new file, all-plus body); appending to the end of a file without quoting the last existing lines; patch-generation tools that emit zero-context diffs.

Related errors


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