{"record":{"id":"60d35356472e862e","repo":"vxcontrol/pentagi","slug":"invalid-diff-line-must-start-with-or","errorCode":null,"errorMessage":"invalid diff line (must start with ' ', '-', or '+'): %q","messagePattern":"invalid diff line \\(must start with ' ', '-', or '\\+'\\): %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/file_diff.go","lineNumber":104,"sourceCode":"\t\t}\n\t\ti++\n\n\t\tfor i < len(lines) && !strings.HasPrefix(lines[i], \"@@\") {\n\t\t\tline := lines[i]\n\t\t\ti++\n\n\t\t\tif strings.HasPrefix(line, `\\`) {\n\t\t\t\t// e.g. \"\\ No newline at end of file\" - not a content line.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif line == \"\" {\n\t\t\t\thunk.lines = append(hunk.lines, diffHunkLine{sign: ' ', text: \"\"})\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tsign := line[0]\n\t\t\tif sign != ' ' && sign != '-' && sign != '+' {\n\t\t\t\treturn nil, fmt.Errorf(\"invalid diff line (must start with ' ', '-', or '+'): %q\", line)\n\t\t\t}\n\t\t\thunk.lines = append(hunk.lines, diffHunkLine{sign: sign, text: line[1:]})\n\t\t}\n\n\t\tif len(hunk.lines) == 0 {\n\t\t\treturn nil, fmt.Errorf(\"hunk %q has no content lines\", header)\n\t\t}\n\t\thunks = append(hunks, hunk)\n\t}\n\n\treturn hunks, nil\n}\n\n// buildLineOffsets returns, for content, the byte offset at which each\n// 1-based line begins: offsets[0] is the (always 0) offset of line 1,\n// offsets[1] of line 2, and so on.\nfunc buildLineOffsets(content string) []int {\n\toffsets := make([]int, 1, strings.Count(content, \"\\n\")+1)","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/file_diff.go#L86-L122","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (context line lost its leading space)\n\"unchanged line\"\n\n// after\n\" unchanged line\"","handlingStrategy":"validation","validationCode":"func hunkBodyValid(diff string) bool {\n\tinHunk := false\n\tfor _, line := range strings.Split(diff, \"\\n\") {\n\t\tif strings.HasPrefix(line, \"@@\") { inHunk = true; continue }\n\t\tif inHunk && line != \"\" && !strings.ContainsAny(line[:1], \" -+\") {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}","typeGuard":null,"tryCatchPattern":"if err := tryApply(diff); err != nil {\n\tif strings.Contains(err.Error(), \"invalid diff line\") {\n\t\tdiff = repairLeadingWhitespace(diff) // re-add missing leading space on context lines\n\t\treturn tryApply(diff)\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["diff","parsing","unified-diff","whitespace"],"backgroundTag":"invalid-diff-line","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}