can1357/oh-my-pi · error · ApplyPatchError

Diff contains ${multiFileCount} file markers. Single-file pa

Error message

Diff contains ${multiFileCount} file markers. Single-file patches cannot contain multi-file markers.

What it means

parseDiffHunks is the single-file patch parser: it counts multi-file markers (e.g. '*** Update File:' / git 'diff --git' style headers) in the input and throws ApplyPatchError if more than one is present. Multi-file patches must go through the multi-file parser; feeding them here would silently merge changes intended for different files into one hunk list.

Source

Thrown at packages/coding-agent/src/edit/diff.ts:809

		if (!candidate) return undefined;
		return candidate.replace(/^(a|b)\//, "");
	}
	if (line.startsWith("*** Update File:")) {
		return line.slice("*** Update File:".length).trim();
	}
	if (line.startsWith("*** Add File:")) {
		return line.slice("*** Add File:".length).trim();
	}
	if (line.startsWith("*** Delete File:")) {
		return line.slice("*** Delete File:".length).trim();
	}
	return undefined;
}

export function parseDiffHunks(diff: string): DiffHunk[] {
	const multiFileCount = countMultiFileMarkers(diff);
	if (multiFileCount > 1) {
		throw new ApplyPatchError(
			`Diff contains ${multiFileCount} file markers. Single-file patches cannot contain multi-file markers.`,
		);
	}

	const normalizedDiff = normalizeDiff(diff);
	const lines = normalizedDiff.split("\n");
	const hunks: DiffHunk[] = [];
	let i = 0;

	while (i < lines.length) {
		const line = lines[i];
		const trimmed = line.trim();

		if (trimmed === "") {
			i++;
			continue;
		}

View on GitHub (pinned to 9690622007)

Solutions

  1. Route the patch to the multi-file parser instead of parseDiffHunks.
  2. Split the patch on its file markers and call parseDiffHunks once per single-file section.
  3. If only one file should change, delete the extra file sections from the patch.
  4. Fix the prompt/tool contract so the model emits one file per patch invocation.

Example fix

// before
parseDiffHunks(patchWithTwoFileMarkers)
// after
for (const section of splitByFileMarkers(patch)) parseDiffHunks(section)
Defensive patterns

Strategy: validation

Validate before calling

const markers = diff.match(/^\*{3} (?:Update|Add|Delete) File:|^diff --git /gm) ?? [];
if (markers.length > 1) {
  throw new Error(`Patch contains ${markers.length} files; split it before parseDiffHunks`);
}

Try / catch

try {
  hunks = parseDiffHunks(diff);
} catch (err) {
  if (err instanceof ApplyPatchError && err.message.includes("file markers")) {
    // switch to the multi-file parser or split on the markers and parse per file
  } else throw err;
}

Prevention

When it happens

Trigger: Calling parseDiffHunks with a patch containing two or more file markers — e.g. a patch updating two files ('*** Update File: a.ts' ... '*** Update File: b.ts') or concatenated git diffs for multiple files.

Common situations: LLM agents emitting a multi-file patch where a single-file one was expected; concatenating several per-file diffs before parsing; choosing the single-file API by mistake when the patch legitimately touches multiple files.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/90b594a5f21b4e92. Report an issue: GitHub.