apply_patch in system prompt is inconsistent with the actual impl

Resolved 💬 3 comments Opened Aug 22, 2025 by caibirdme Closed Sep 27, 2025
💡 Likely answer: A maintainer (dylan-hurd-oai, contributor) responded on this thread — see the highlighted reply below.

What version of Codex is running?

master

Which model were you using?

gpt5

What platform is your computer?

linux

What steps can reproduce the bug?

in src/core/prompt.md:

## `apply_patch`

Your patch language is a stripped‑down, file‑oriented diff format designed to be easy to parse and safe to apply. You can think of it as a high‑level envelope:

**_ Begin Patch
[ one or more file sections ]
_** End Patch

Within that envelope, you get a sequence of file operations.
You MUST include a header to specify the action you are taking.
Each operation starts with one of three headers:

**_ Add File: <path> - create a new file. Every following line is a + line (the initial contents).
_** Delete File: <path> - remove an existing file. Nothing follows.
\*\*\* Update File: <path> - patch an existing file in place (optionally with a rename).

May be immediately followed by \*\*\* Move to: <new path> if you want to rename the file.
Then one or more “hunks”, each introduced by @@ (optionally followed by a hunk header).
Within a hunk each line starts with:

- for inserted text,

* for removed text, or
  space ( ) for context.
  At the end of a truncated hunk you can emit \*\*\* End of File.

Patch := Begin { FileOp } End
Begin := "**_ Begin Patch" NEWLINE
End := "_** End Patch" NEWLINE
FileOp := AddFile | DeleteFile | UpdateFile
AddFile := "**_ Add File: " path NEWLINE { "+" line NEWLINE }
DeleteFile := "_** Delete File: " path NEWLINE
UpdateFile := "**_ Update File: " path NEWLINE [ MoveTo ] { Hunk }
MoveTo := "_** Move to: " newPath NEWLINE
Hunk := "@@" [ header ] NEWLINE { HunkLine } [ "*** End of File" NEWLINE ]
HunkLine := (" " | "-" | "+") text NEWLINE

A full patch can combine several operations:

**_ Begin Patch
_** Add File: hello.txt
+Hello world
**_ Update File: src/app.py
_** Move to: src/main.py
@@ def greet():
-print("Hi")
+print("Hello, world!")
**_ Delete File: obsolete.txt
_** End Patch

You told llm to use **_ Begin Patch, _** End Patch, **_ Add File ...
But in apply-patch.rs, the parse want just ***

//! The official Lark grammar for the apply-patch format is:
//!
//! start: begin_patch hunk+ end_patch
//! begin_patch: "*** Begin Patch" LF
//! end_patch: "*** End Patch" LF?
//!
//! hunk: add_hunk | delete_hunk | update_hunk
//! add_hunk: "*** Add File: " filename LF add_line+
//! delete_hunk: "*** Delete File: " filename LF
//! update_hunk: "*** Update File: " filename LF change_move? change?
//! filename: /(.+)/
//! add_line: "+" /(.+)/ LF -> line
//!
//! change_move: "*** Move to: " filename LF
//! change: (change_context | change_line)+ eof_line?
//! change_context: ("@@" | "@@ " /(.+)/) LF
//! change_line: ("+" | "-" | " ") /(.+)/ LF
//! eof_line: "*** End of File" LF
//!
//! The parser below is a little more lenient than the explicit spec and allows for
//! leading/trailing whitespace around patch markers.

Which will confuse the llm

What is the expected behavior?

keep the prompt consistent with the parser logic

What do you see instead?

_No response_

Additional information

_No response_

View original on GitHub ↗

3 Comments

Oktai15 · 1 year ago

@dylan-hurd-oai, hi! I want to add some more information about apply_patch problem:

TL;DR: Nested @@ context headers are documented but not supported (parser treats second @@ as an error)

The .md file for apply_patch describe a “nested” context feature: you can place multiple @@ headers in a single hunk to progressively narrow the search (e.g., class → method). However, the current implementation rejects a second @@ within the same hunk.

This is both a docs/behavior mismatch and a practical problem.

Affected code is here: parser.rs, function parse_update_file_chunk. It accepts one context header per hunk and then expect only diff lines (' ', '+', '-') or the EOF marker. Any additional @@ is treated as an unexpected line (error) or as the start of a new hunk (which changes semantics).

Steps to reproduce:
Using any file (e.g., src/app.py), try to apply a patch with two @@ lines in the same hunk:

*** Begin Patch
*** Update File: src/app.py
@@ class BaseClass
@@     def method():
- old_line
+ new_line
*** End Patch

Actual result:
Parsing fails. In Rust, parse_update_file_chunk consumes the first @@ and then sees the second @@ where it expects a diff line; since parsed_lines == 0, it errors with something like:

Unexpected line found in update hunk: '@@     def method()'. Every line should start with ' ' (context), '+' (added), or '-' (removed)

Expected result

Per the docs, multiple @@ headers in a single hunk should be allowed to refine context, e.g.:

@@ class BaseClass
@@     def method():
[context_before]
- old
+ new
[context_after]

The hunk should search for class BaseClass, then within/after that, search for def method(), and apply the change there.

Oktai15 · 1 year ago

@caibirdme your problem is resolved, actually, because now prompt doesn't have information about apply_patch. It happened here.

dylan-hurd-oai contributor · 1 year ago

Great bug report, thanks. We have indeed resolved the instructions formatting issue, but are continuing to make this behavior more robust. Leaving this issue open for simplicity, but for future reference, would be helpful to track different apply_patch issues separately.