Hmbown/CodeWhale · error
only *** Update File patches are supported
Error message
only *** Update File patches are supported
What it means
Only update patches are supported: line 2 must be `*** Update File: <workspace-relative path>` (eval.rs:688). A missing second line or any other directive — `*** Add File:`, `*** Delete File:`, `*** Move to:` — fails before the file is opened.
Source
Thrown at crates/tui/src/eval.rs:688
content.push('\n');
}
content.push_str(line);
content.push('\n');
fs::write(path, content).with_context(|| format!("failed to write {}", path.display()))
}
fn apply_patch(root: &Path, patch: &str) -> Result<()> {
let mut lines = patch.lines();
let begin = lines.next().unwrap_or_default();
if begin != "*** Begin Patch" {
return Err(anyhow!("patch missing *** Begin Patch header"));
}
let header = lines.next().unwrap_or_default();
let file_rel = header
.strip_prefix("*** Update File: ")
.ok_or_else(|| anyhow!("only *** Update File patches are supported"))?;
if file_rel.contains("..") {
return Err(anyhow!("patch path must be workspace-relative"));
}
let file_path = root.join(file_rel);
let original = read_workspace_file(&file_path)?;
let had_trailing_newline = original.ends_with('\n');
let mut file_lines: Vec<String> = original.lines().map(|l| l.to_string()).collect();
let mut cursor = 0usize;
for raw_line in lines {
if raw_line == "*** End Patch" {
break;
}
if raw_line.starts_with("*** ") {
return Err(anyhow!("unexpected patch directive: {raw_line}"));
}
if raw_line.starts_with("@@") {View on GitHub (pinned to 8880682c63)
Solutions
- Express the change as an update to an existing file
- For new files, create the file first (write initial content via the write path), then send an update patch — or skip apply_patch and write directly
- Split multi-operation patches into single-file updates
Example fix
*** before *** Begin Patch *** Add File: notes.md +hello *** after (create empty notes.md first, then) *** Begin Patch *** Update File: notes.md @@ +hello *** End Patch
Defensive patterns
Strategy: validation
Validate before calling
let mut lines = patch.lines();
anyhow::ensure!(lines.next() == Some("*** Begin Patch"), "bad patch header");
anyhow::ensure!(
lines.next().unwrap_or_default().starts_with("*** Update File: "),
"only single-file update patches are supported here"
); Type guard
fn is_update_patch(patch: &str) -> bool {
let mut lines = patch.lines();
lines.next() == Some("*** Begin Patch")
&& lines.next().unwrap_or_default().starts_with("*** Update File: ")
} Prevention
- State the single-file-update contract in the model prompt
- Handle file creation and deletion through write/delete tool paths, not patches
- Validate the second-line directive before applying
When it happens
Trigger: The patch tries to create, delete, or move a file instead of updating one; the header line is blank; the directive spelling differs.
Common situations: Model mixes the OpenAI apply-patch dialect (Add/Delete/Move) into its output; multi-operation edits batched into one patch.
Related errors
- patch missing *** Begin Patch header
- unexpected patch directive: {raw_line}
- unsupported patch line: {raw_line}
- patch context not found in {}: {}
- patch removal mismatch in {}: expected '{}'
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/4eca5e825fdaa0c2.
Report an issue: GitHub.