{"record":{"id":"bb82544fa50c315a","repo":"can1357/oh-my-pi","slug":"operation-operationnumber-pattern-is-too-broad","errorCode":null,"errorMessage":"Operation ${operationNumber} pattern is too broad; add another distinctive ${GAP} fragment.","messagePattern":"Operation (.+?) pattern is too broad; add another distinctive (.+?) fragment\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/edit/sloppy.ts","lineNumber":2415,"sourceCode":"\t\treturn (\n\t\t\tselection !== undefined &&\n\t\t\tcapturesAreIdentical(selection.captureIndices.slice(0, rewriteGapCount(replacement)), candidates)\n\t\t);\n\t});\n}\n\nfunction locate(\n\tcontent: string,\n\tpattern: ParsedPattern,\n\toperation: Operation,\n\toperationNumber: number,\n\tpath: string,\n\texclusions?: ReadonlyArray<{ start: number; end: number }>,\n): Candidate[] {\n\tconst normalized = normalizeText(content);\n\tconst raw = collectCandidates(content, normalized, pattern, \"raw\");\n\tif (raw.overflow) {\n\t\tthrow new Error(`Operation ${operationNumber} pattern is too broad; add another distinctive ${GAP} fragment.`);\n\t}\n\tif (raw.candidates.length === 0 && hasMarkerLines(operation.sourcePatternText)) {\n\t\tthrow new Error(\n\t\t\t`Operation ${operationNumber} adds or removes whole lines but MATCH did not match byte-for-byte. Re-read the region and copy its exact indentation.`,\n\t\t);\n\t}\n\tif (raw.candidates.length === 0 && pattern.literalFallback) {\n\t\tconst exact = exactOccurrences(normalized.text, pattern.literalFallback.normalized);\n\t\tif (exact.length > 0 && (operation.all || exact.length === 1)) {\n\t\t\tconst fallbackCandidates = exact.map(occurrence => {\n\t\t\t\tconst matchStart = sourceStart(normalized, occurrence.start, 0);\n\t\t\t\tconst matchEnd = sourceEnd(normalized, occurrence.end, content.length);\n\t\t\t\tconst fallbackStart = occurrence.start + pattern.literalFallback!.selectionStart;\n\t\t\t\tconst fallbackEnd = occurrence.start + pattern.literalFallback!.selectionEnd;\n\t\t\t\tconst start =\n\t\t\t\t\tpattern.literalFallback!.selectionStart === pattern.literalFallback!.normalized.length\n\t\t\t\t\t\t? matchEnd\n\t\t\t\t\t\t: sourceStart(normalized, fallbackStart, matchEnd);","sourceCodeStart":2397,"sourceCodeEnd":2433,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/edit/sloppy.ts#L2397-L2433","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst pattern = \"return true;\\n...\\n}\";\n// after\nconst pattern = \"function isValid(user) {\\nreturn true;\\n...\\n}\";","handlingStrategy":"validation","validationCode":"// Before applying, count occurrences of the pattern's literal lines in the file;\n// if the lines are highly repeated, add a distinguishing fragment first.\nconst anchorLines = pattern.split(\"\\n\").filter(l => l.trim() && !l.includes(\"...\"));\nfor (const line of anchorLines) {\n  const count = content.split(line.trim()).length - 1;\n  if (count > 5) throw new Error(`anchor line appears ${count} times; add more context`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await applySloppyEdit({ pattern });\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"too broad\")) {\n    // rebuild pattern with an additional distinctive fragment between gaps\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["edit-pattern","matching","too-many-candidates"],"backgroundTag":"edit-pattern-too-broad","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}