vxcontrol/pentagi · error
invalid diff line (must start with ' ', '-', or '+'): %q
Error message
invalid diff line (must start with ' ', '-', or '+'): %q
What it means
Within a hunk, every body line must begin with ' ' (context), '-' (removal), or '+' (addition). parseUnifiedDiff rejects any other first character. This catches diffs using '\ No newline at end of file' incorrectly placed, '!' markers from context diffs, or lines missing their leading space.
Source
Thrown at backend/pkg/tools/file_diff.go:104
}
i++
for i < len(lines) && !strings.HasPrefix(lines[i], "@@") {
line := lines[i]
i++
if strings.HasPrefix(line, `\`) {
// e.g. "\ No newline at end of file" - not a content line.
continue
}
if line == "" {
hunk.lines = append(hunk.lines, diffHunkLine{sign: ' ', text: ""})
continue
}
sign := line[0]
if sign != ' ' && sign != '-' && sign != '+' {
return nil, fmt.Errorf("invalid diff line (must start with ' ', '-', or '+'): %q", line)
}
hunk.lines = append(hunk.lines, diffHunkLine{sign: sign, text: line[1:]})
}
if len(hunk.lines) == 0 {
return nil, fmt.Errorf("hunk %q has no content lines", header)
}
hunks = append(hunks, hunk)
}
return hunks, nil
}
// buildLineOffsets returns, for content, the byte offset at which each
// 1-based line begins: offsets[0] is the (always 0) offset of line 1,
// offsets[1] of line 2, and so on.
func buildLineOffsets(content string) []int {
offsets := make([]int, 1, strings.Count(content, "\n")+1)View on GitHub (pinned to ea665308ba)
Solutions
- Check the quoted line in the error and ensure it begins with exactly one of ' ', '-', or '+'.
- Re-add stripped leading spaces on context lines — every unchanged line needs a single leading space.
- Regenerate the diff in unified format (git diff, diff -u) instead of context or other formats.
- Avoid channels that collapse whitespace (chat markdown, email) when moving diffs; use files or base64.
Example fix
// before (context line lost its leading space) "unchanged line" // after " unchanged line"
Defensive patterns
Strategy: validation
Validate before calling
func hunkBodyValid(diff string) bool {
inHunk := false
for _, line := range strings.Split(diff, "\n") {
if strings.HasPrefix(line, "@@") { inHunk = true; continue }
if inHunk && line != "" && !strings.ContainsAny(line[:1], " -+") {
return false
}
}
return true
} Try / catch
if err := tryApply(diff); err != nil {
if strings.Contains(err.Error(), "invalid diff line") {
diff = repairLeadingWhitespace(diff) // re-add missing leading space on context lines
return tryApply(diff)
}
return err
} Prevention
- Never trim leading whitespace from diff body lines in pipelines
- Transfer diffs via files or base64, not whitespace-collapsing channels (chat, email)
- Use unified format only; reject context-format diffs ('!' '*' markers) up front
- Inspect a sample hunk visually before automated application
When it happens
Trigger: A hunk body line starts with a character other than ' ', '-', '+' — e.g. a context line whose leading space was stripped by an editor or chat formatting, a '!'/'*' context-diff marker, or a line beginning with '\\' inside the hunk.
Common situations: Markdown/chat pipelines strip leading whitespace from diff lines, turning context lines into invalid lines; tools emit context-format diffs instead of unified; copying diffs from terminals where the leading space is invisible and gets lost.
Related errors
- diff contains no hunks (no "@@ ... @@" header found)
- invalid hunk header: %q
- invalid hunk header %q: %w
- hunk %q has no content lines
- failed to apply diff to %s: %w
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/60d35356472e862e.
Report an issue: GitHub.