Skip to content

fix(runtime): accept blank context lines in apply_patch hunks - #174

Open
kevin9327 wants to merge 1 commit into
deer-flow:mainfrom
kevin9327:fix/apply-patch-blank-context-line
Open

kevin9327 wants to merge 1 commit into
deer-flow:mainfrom
kevin9327:fix/apply-patch-blank-context-line

Conversation

@kevin9327

Copy link
Copy Markdown

Summary

When an agent edits a file with the built-in apply_patch tool and one of its @@ hunks contains a blank line written as a truly empty line (no leading space), the whole patch is rejected with Invalid hunk line (expected space, "+", or "-"): and nothing is written. Models produce this shape often: a blank context line between two statements, or an empty line separating two *** Update File: sections. The tool description tells the model it applies "the Codex patch format", and Codex accepts both.

The Codex reference (codex-rs/apply-patch) handles this in two places, mirrored here:

  • A bare empty line inside an update hunk is read as an empty context line (streaming_parser.rs: "The normal parser treats a bare empty line in an update hunk as an empty context line").
  • If a hunk's old lines end with such an empty line and the match fails, the match is retried without it, because it stands for the final newline, which is not a separate element after the file is split into lines (file_update.rs).

Non-blank lines without a diff marker are still rejected.

Validation

bun test packages/runtime/tests/tools/built-in/apply-patch.test.ts

Before the fix (new tests added, source unchanged): 8 pass, 1 fail.

packages\runtime\tests\tools\built-in\apply-patch.test.ts:
189 |           } else if (marker === "-") {
190 |             oldLines.push(content);
191 |           } else if (marker === "+") {
192 |             newLines.push(content);
193 |           } else {
194 |             throw new Error(`Invalid hunk line (expected space, "+", or "-"): ${line}`);
                            ^
error: Invalid hunk line (expected space, "+", or "-"): 
      at _parsePatch (packages\runtime\src\tools\built-in\apply-patch.ts:194:23)
      at applyPatch (packages\runtime\src\tools\built-in\apply-patch.ts:41:19)
      at <anonymous> (packages\runtime\tests\tools\built-in\apply-patch.test.ts:159:11)
(fail) apply_patch built-in > treats bare blank lines in update hunks as empty context [2.44ms]

 8 pass
 1 fail
 16 expect() calls
Ran 9 tests across 1 file. [479.00ms]

After the fix: 9 pass, 0 fail.

  • still rejects non-blank hunk lines without a diff marker passes both before and after, which shows the parser is not widened beyond bare empty lines. The 7 existing tests are unchanged and pass.
  • bun test packages/runtime/tests/tools/built-in/built-in-tools-module.test.ts: 5 pass / 1 fail on both main and this branch. The failure (runs bash commands from the workspace root) is pre-existing locally because that test spawns bash.
  • ESLint (--max-warnings 0) on both touched files: clean on main and on this branch.
  • tsc --noEmit -p packages/runtime/tsconfig.json: clean on main and on this branch.
  • Prettier: both files already have unformatted lines on main (16 and 6); this change adds none.

🤖 Generated with Claude Code

An update hunk that contained a bare empty line (a blank context line
without its leading space, or an empty line separating two file
sections) failed with "Invalid hunk line". Codex reads such a line as an
empty context line, and retries a match without a trailing empty context
line because it stands for the final newline. Do the same.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant