{"record":{"id":"881c6f5bd2e16955","repo":"can1357/oh-my-pi","slug":"found-result-matchcount-matches-for-context","errorCode":null,"errorMessage":"Found ${result.matchCount} matches for context '${displayContext}' in ${path}.${strategyHint}${previewText}\\n\\nAdd more surrounding context or additional @@ anchors to make it unique.","messagePattern":"Found (.+?) matches for context '(.+?)' in (.+?)\\.(.+?)(.+?)\\\\n\\\\nAdd more surrounding context or additional @@ anchors to make it unique\\.","errorType":"validation","errorClass":"ApplyPatchError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/edit/modes/patch.ts","lineNumber":1142,"sourceCode":"\t\t\tif (idx === undefined || (result.matchCount !== undefined && result.matchCount > 1)) {\n\t\t\t\tconst fallback = attemptSequenceFallback(\n\t\t\t\t\toriginalLines,\n\t\t\t\t\thunk,\n\t\t\t\t\tlineIndex,\n\t\t\t\t\tlineHint,\n\t\t\t\t\tallowFuzzy,\n\t\t\t\t\tallowAggressiveFallbacks,\n\t\t\t\t);\n\t\t\t\tif (fallback !== undefined) {\n\t\t\t\t\tlineIndex = fallback;\n\t\t\t\t} else if (result.matchCount !== undefined && result.matchCount > 1) {\n\t\t\t\t\tconst displayContext = hunk.changeContext.includes(\"\\n\")\n\t\t\t\t\t\t? hunk.changeContext.split(\"\\n\").pop()\n\t\t\t\t\t\t: hunk.changeContext;\n\t\t\t\t\tconst previews = formatSequenceMatchPreviews(originalLines, result.matchIndices, result.matchCount);\n\t\t\t\t\tconst strategyHint = result.strategy ? ` Matching strategy: ${result.strategy}.` : \"\";\n\t\t\t\t\tconst previewText = previews ? `\\n\\n${previews}` : \"\";\n\t\t\t\t\tthrow new ApplyPatchError(\n\t\t\t\t\t\t`Found ${result.matchCount} matches for context '${displayContext}' in ${path}.${strategyHint}` +\n\t\t\t\t\t\t\t`${previewText}\\n\\nAdd more surrounding context or additional @@ anchors to make it unique.`,\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tconst displayContext = hunk.changeContext.includes(\"\\n\")\n\t\t\t\t\t\t? hunk.changeContext.split(\"\\n\").join(\" > \")\n\t\t\t\t\t\t: hunk.changeContext;\n\t\t\t\t\tthrow new ApplyPatchError(`Failed to find context '${displayContext}' in ${path}`);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If oldLines[0] matches the final context, start search at idx (not idx+1)\n\t\t\t\t// This handles the common case where @@ scope and first context line are identical\n\t\t\t\tconst firstOldLine = hunk.oldLines[0];\n\t\t\t\tconst finalContext = hunk.changeContext.includes(\"\\n\")\n\t\t\t\t\t? hunk.changeContext.split(\"\\n\").pop()?.trim()\n\t\t\t\t\t: hunk.changeContext.trim();\n\t\t\t\tconst isHierarchicalContext =\n\t\t\t\t\thunk.changeContext.includes(\"\\n\") || hunk.changeContext.trim().split(/\\s+/).length > 2;","sourceCodeStart":1124,"sourceCodeEnd":1160,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/edit/modes/patch.ts#L1124-L1160","documentation":"The hunk had a @@ changeContext anchor, and findHierarchicalContext found that the anchor text matches more than one location in the file (matchCount > 1). Since the patcher cannot decide which occurrence to modify, it throws with the number of matches, the matching strategy, and previews of each match location. This is a deliberate ambiguity guard, not a lookup failure.","triggerScenarios":"An @@ anchor such as `@@ functionName` or a context line matches multiple functions/occurrences in the file, and no line hint or sequence fallback can disambiguate (attemptSequenceFallback returned undefined).","commonSituations":"Editing a method whose name appears in several classes (overloads, interface + implementation); changing a line like `return null;` that appears many times; duplicated boilerplate blocks; anchor that is too short/generic (e.g. `@@ handler`).","solutions":["Make the @@ anchor more specific: use hierarchical anchors (`@@ ClassName\\n@@ methodName`) or include more of the enclosing scope.","Add more surrounding context lines to the hunk so the target block is unique.","Add a correct oldStartLine hint — a hint near the intended occurrence resolves ambiguity within the hint window.","Rename duplicated code first, or split the patch into multiple smaller patches each targeting a unique site."],"exampleFix":"// before\n@@ handler\n-old handler body\n+new handler body\n\n// after\n@@ RequestController\n@@ onTimeout\n-old handler body\n+new handler body","handlingStrategy":"validation","validationCode":"const content = await Bun.file(path).text();\nconst occurrences = content.split('\\n').filter(l => l.includes(anchor)).length;\nif (occurrences > 1) {\n  throw new Error(`Anchor '${anchor}' is ambiguous (${occurrences} matches); use a hierarchical @@ anchor or line hint.`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  applyPatch(patch);\n} catch (err) {\n  if (err instanceof ApplyPatchError && /Found \\d+ matches for context/.test(err.message)) {\n    // inspect previews in the message, add disambiguating context, retry\n  } else throw err;\n}","preventionTips":["Make @@ anchors hierarchical: outer scope then inner member.","Count anchor occurrences in the file before patching.","Add a line hint when editing one of several identical sites.","Keep hunks small and anchored to unique nearby text."],"tags":["patch","ambiguity","context-matching"],"backgroundTag":"patch-ambiguous-match","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}