gitbutlerapp/gitbutler · warning · Error

Failed to parse diff header

Error message

Failed to parse diff header

What it means

The agent-cleanup rewrite writes files atomically: read content, write a temp file in the same directory, then rename over the target. Right before persisting, it re-reads the target and compares to the snapshot it based the rewrite on; if they differ (someone wrote in between), it bails instead of silently discarding that edit. A later sweep re-runs on the fresh content, so backing off is safe.

Source

Thrown at packages/ui/src/lib/utils/diffParsing.ts:168

	readonly newLines: number;
	readonly comment?: string;
	readonly contentSections: ContentSection[];
};

type BaseDiffRows = { prevRows: BaseRow[]; nextRows: BaseRow[] };

const headerRegex =
	/@@ -(?<beforeStart>\d+),?(?<beforeCount>\d+)? \+(?<afterStart>\d+),?(?<afterCount>\d+)? @@(?<comment>.+)?/;
function parseHeader(header: string): {
	oldStart: number;
	newStart: number;
	oldLines: number;
	newLines: number;
	comment?: string;
} {
	const result = headerRegex.exec(header);
	if (!result?.groups) {
		throw new Error("Failed to parse diff header");
	}
	return {
		oldStart: parseInt(result.groups["beforeStart"]),
		oldLines: parseInt(result.groups["beforeCount"] ?? "1"),
		newStart: parseInt(result.groups["afterStart"]),
		newLines: parseInt(result.groups["afterCount"] ?? "1"),
		comment: result.groups["comment"],
	};
}

function lineType(line: string): SectionType {
	if (line.startsWith("+")) {
		return SectionType.AddedLines;
	} else if (line.startsWith("-")) {
		return SectionType.RemovedLines;
	} else {
		return SectionType.Context;
	}

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Retry the sweep: re-running the cleanup command re-reads the fresh content and reapplies the rewrite
  2. Avoid running two rewriting commands over the same file simultaneously; serialize cleanups in your tooling
  3. If it persists, check for a formatter/watcher that keeps touching the file and pause it during the sweep

Example fix

# shell
# before: 'file changed while preparing the rewrite; leaving it alone'
 but agent cleanup  # simply re-run; the sweep is idempotent over fresh content
# after: rewrite applies cleanly
Defensive patterns

Strategy: retry

Try / catch

match apply_rewrite(path, new_content) {
    Err(err) if err.to_string().contains("changed while preparing") => {
        // benign back-off: re-read the file and re-run the sweep on fresh content
    }
    other => other,
}

Prevention

When it happens

Trigger: The managed file (e.g. an AGENTS.md/CLAUDE.md-style file with managed blocks) is modified between the initial read and the rename - another agent, editor autosave, formatter, or concurrent but command writing the same file while the cleanup sweep is in flight.

Common situations: Multiple agents/tools editing instruction files concurrently; IDE autosave or a linter rewriting the file mid-sweep; slow disks enlarging the read-to-rename window.

Understand the failure class

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/b2993c5f03ad1c0e. Report an issue: GitHub.