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
- Add another distinctive literal fragment between or around the existing `...` gaps (function name, unique identifier, literal string).
- Shorten the pattern to only the unique region instead of matching a wide span of common lines.
- 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
- Check how many times your anchor lines repeat before constructing the pattern.
- Prefer unique identifiers, string literals, or declarations as fragments.
- For repetitive files, include the enclosing named block in the pattern span.
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
- Operation ${operationNumber} adds or removes whole lines but
- Operation ${operationNumber} did not match ${path}: your lin
- ${operation.all ? `Operation ${operationNumber} ${OPENER}* f
- Operation ${operationNumber} is ambiguous: ${candidates.leng
- Operation ${operationNumber} has no visible current text.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/bb82544fa50c315a.
Report an issue: GitHub.