Hmbown/CodeWhale · error

unsupported patch line: {raw_line}

Error message

unsupported patch line: {raw_line}

What it means

Every patch body line must begin with ` `, `-`, `+`, or `@@`; `*** End Patch` terminates input (eval.rs:742). A line whose first character is anything else — including a truly empty line (blank context must be a single space) or a `\ No newline at end of file` marker — is unsupported.

Source

Thrown at crates/tui/src/eval.rs:742

                    ));
                };
                cursor = found + 1;
            }
            "-" => {
                if cursor >= file_lines.len() || file_lines[cursor] != content {
                    return Err(anyhow!(
                        "patch removal mismatch in {}: expected '{}'",
                        file_path.display(),
                        content
                    ));
                }
                file_lines.remove(cursor);
            }
            "+" => {
                file_lines.insert(cursor, content);
                cursor += 1;
            }
            _ => return Err(anyhow!("unsupported patch line: {raw_line}")),
        }
    }

    let mut updated = file_lines.join("\n");
    if had_trailing_newline {
        updated.push('\n');
    }

    fs::write(&file_path, updated)
        .with_context(|| format!("failed to write patched file {}", file_path.display()))
}

fn run_bash(root: &Path, command: &str) -> Result<String> {
    crate::shell_dispatcher::global_dispatcher().run_foreground(command, root)
}

fn truncate_output(value: &str, max_chars: usize) -> String {
    if value.chars().count() <= max_chars {

View on GitHub (pinned to 8880682c63)

Solutions

  1. Ensure every body line keeps its prefix character; blank context lines are exactly one space
  2. Strip `\ No newline at end of file` and other non-format lines before applying
  3. Validate line prefixes up front

Example fix

// before: context lines lost their leading space
// after: re-prefix unsupported lines
let fixed: Vec<String> = patch.lines().map(|l| {
    match l.chars().next() {
        Some(' ') | Some('-') | Some('+') | Some('@') => l.to_string(),
        _ => format!(" {l}"),
    }
}).collect();
Defensive patterns

Strategy: validation

Validate before calling

fn patch_lines_supported(patch: &str) -> bool {
    patch.lines()
        .skip(2)
        .take_while(|l| *l != "*** End Patch")
        .all(|l| {
            !l.starts_with("*** ")
                && matches!(l.chars().next(), Some(' ') | Some('-') | Some('+') | Some('@'))
        })
}
anyhow::ensure!(patch_lines_supported(&patch), "patch contains unsupported lines");

Type guard

fn patch_lines_supported(patch: &str) -> bool {
    patch.lines()
        .skip(2)
        .take_while(|l| *l != "*** End Patch")
        .all(|l| {
            !l.starts_with("*** ")
                && matches!(l.chars().next(), Some(' ') | Some('-') | Some('+') | Some('@'))
        })
}

Prevention

When it happens

Trigger: Model or transport strips the leading space from context lines; blank lines emitted with no prefix; unified-diff artifacts like `\ No newline at end of file` leak into the patch body.

Common situations: Whitespace-trimming editors or transports; dialect mixing from different diff formats.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/79b1a6e43bd6be52. Report an issue: GitHub.