can1357/oh-my-pi · error

Operation ${operationNumber} pattern is too broad; add anoth

Error message

Operation ${operationNumber} pattern is too broad; add another distinctive ${GAP} fragment.

What it means

During candidate collection, the raw (byte-for-byte, whitespace-normalized) match produced an overflow — more distinct candidate regions than the tool will consider, meaning the pattern fragments are not selective enough. The library throws and asks for another distinctive `...` fragment to narrow the search space.

Source

Thrown at packages/coding-agent/src/edit/sloppy.ts:2415

		return (
			selection !== undefined &&
			capturesAreIdentical(selection.captureIndices.slice(0, rewriteGapCount(replacement)), candidates)
		);
	});
}

function locate(
	content: string,
	pattern: ParsedPattern,
	operation: Operation,
	operationNumber: number,
	path: string,
	exclusions?: ReadonlyArray<{ start: number; end: number }>,
): Candidate[] {
	const normalized = normalizeText(content);
	const raw = collectCandidates(content, normalized, pattern, "raw");
	if (raw.overflow) {
		throw new Error(`Operation ${operationNumber} pattern is too broad; add another distinctive ${GAP} fragment.`);
	}
	if (raw.candidates.length === 0 && hasMarkerLines(operation.sourcePatternText)) {
		throw new Error(
			`Operation ${operationNumber} adds or removes whole lines but MATCH did not match byte-for-byte. Re-read the region and copy its exact indentation.`,
		);
	}
	if (raw.candidates.length === 0 && pattern.literalFallback) {
		const exact = exactOccurrences(normalized.text, pattern.literalFallback.normalized);
		if (exact.length > 0 && (operation.all || exact.length === 1)) {
			const fallbackCandidates = exact.map(occurrence => {
				const matchStart = sourceStart(normalized, occurrence.start, 0);
				const matchEnd = sourceEnd(normalized, occurrence.end, content.length);
				const fallbackStart = occurrence.start + pattern.literalFallback!.selectionStart;
				const fallbackEnd = occurrence.start + pattern.literalFallback!.selectionEnd;
				const start =
					pattern.literalFallback!.selectionStart === pattern.literalFallback!.normalized.length
						? matchEnd
						: sourceStart(normalized, fallbackStart, matchEnd);

View on GitHub (pinned to 9690622007)

Solutions

  1. Add another distinctive literal fragment between or around the existing `...` gaps (function name, unique identifier, literal string).
  2. Shorten the pattern to only the unique region instead of matching a wide span of common lines.
  3. If the edit should apply to all occurrences, use the `*` (all) form instead of a single ambiguous match.

Example fix

// before
const pattern = "return true;\n...\n}";
// after
const pattern = "function isValid(user) {\nreturn true;\n...\n}";
Defensive patterns

Strategy: validation

Validate before calling

// Before applying, count occurrences of the pattern's literal lines in the file;
// if the lines are highly repeated, add a distinguishing fragment first.
const anchorLines = pattern.split("\n").filter(l => l.trim() && !l.includes("..."));
for (const line of anchorLines) {
  const count = content.split(line.trim()).length - 1;
  if (count > 5) throw new Error(`anchor line appears ${count} times; add more context`);
}

Try / catch

try {
  await applySloppyEdit({ pattern });
} catch (err) {
  if (err instanceof Error && err.message.includes("too broad")) {
    // rebuild pattern with an additional distinctive fragment between gaps
  }
  throw err;
}

Prevention

When it happens

Trigger: A pattern whose literal fragments are common/repetitive so `collectCandidates(..., "raw")` sets `overflow: true` (candidate count exceeded the internal limit) — e.g. a short repeated line like `}` or a common import line appearing dozens of times.

Common situations: Editing generated or highly repetitive code (interfaces, enums, long switch statements) where the chosen anchor line repeats many times; patterns built from template files applied to many similar blocks.

Related errors


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