{"record":{"id":"31142b5bfc3c22f5","repo":"danny-avila/LibreChat","slug":"old-text-matched-match-count-locations-with-m","errorCode":null,"errorMessage":"old_text matched ${match.count} locations with ${match.strategy}; make it unique before retrying.","messagePattern":"old_text matched (.+?) locations with (.+?); make it unique before retrying\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/api/src/agents/handlers.ts","lineNumber":1106,"sourceCode":"    return whitespaceNormalized;\n  }\n  return findLineWindowMatch(content, needle, 'indentation-flexible');\n}\n\nfunction applyTextEdits(\n  content: string,\n  edits: TextEdit[],\n): { content: string; strategies: string[] } {\n  let working = content;\n  const strategies: string[] = [];\n\n  for (const edit of edits) {\n    const match = findReplacementMatch(working, edit.old_text);\n    if (match.status === 'none') {\n      throw new Error('old_text did not match the file content.');\n    }\n    if (match.status === 'ambiguous') {\n      throw new Error(\n        `old_text matched ${match.count} locations with ${match.strategy}; make it unique before retrying.`,\n      );\n    }\n    working =\n      working.slice(0, match.index) + edit.new_text + working.slice(match.index + match.length);\n    strategies.push(match.strategy);\n  }\n\n  return { content: working, strategies };\n}\n\nfunction formatRange(start: number, count: number): string {\n  return count === 1 ? String(start) : `${start},${count}`;\n}\n\nfunction createUnifiedDiff(filePath: string, oldContent: string, newContent: string): string {\n  if (oldContent === newContent) {\n    return '';","sourceCodeStart":1088,"sourceCodeEnd":1124,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/packages/api/src/agents/handlers.ts#L1088-L1124","documentation":"Thrown by applyTextEdits when findReplacementMatch returns status 'ambiguous': old_text matches more than one location under a given strategy (exact, line-trimmed, whitespace-normalized, or indentation-flexible). The message reports the count and the strategy that hit multiple matches. The tool refuses to guess, requiring the caller to make old_text unambiguous before retrying.","triggerScenarios":"old_text is a short/repeated snippet (a common import line, a single closing brace, a duplicated function signature) that appears 2+ times; even after the looser normalization strategies the matches stay plural.","commonSituations":"Editing boilerplate that repeats across a file (log lines, return statements, similar methods); old_text too small to be unique; the file has duplicate blocks and the edit needs disambiguation.","solutions":["Expand old_text to include enough preceding/following unique lines so only one location matches.","Use the reported strategy hint: if it matched under 'whitespace-normalized', the exact text differs only by whitespace — add distinguishing content lines.","If you genuinely want to replace all occurrences, issue separate edits targeting each one with unique context."],"exampleFix":"// before (ambiguous: 'return 0;' appears 5 times)\n{ old_text: \"  return 0;\", new_text: \"  return -1;\" }\n\n// after (unique via surrounding context)\n{ old_text: \"function getDefault() {\\n  return 0;\\n}\", new_text: \"function getDefault() {\\n  return -1;\\n}\" }","handlingStrategy":"validation","validationCode":"function countMatches(content: string, needle: string): number {\n  let count = 0, from = 0;\n  while (true) {\n    const i = content.indexOf(needle, from);\n    if (i === -1) break;\n    count++;\n    from = i + Math.max(1, needle.length);\n  }\n  return count;\n}\nfor (const e of edits) {\n  const n = countMatches(currentContent, e.old_text);\n  if (n > 1) throw new Error(`old_text is ambiguous (${n} matches); add unique context.`);\n}","typeGuard":"function isOldTextUnique(content: string, oldText: string): boolean {\n  const first = content.indexOf(oldText);\n  return first !== -1 && content.indexOf(oldText, first + Math.max(1, oldText.length)) === -1;\n}","tryCatchPattern":"try {\n  const { content, strategies } = applyTextEdits(current.content, edits);\n} catch (e) {\n  if (e instanceof Error && /ambiguous/.test(e.message)) {\n    // expand old_text with neighboring lines to disambiguate, then retry\n  } else throw e;\n}","preventionTips":["Include distinctive surrounding lines in old_text so only one location matches.","Avoid editing repeated boilerplate with a tiny snippet.","For repeated patterns, target each occurrence separately with unique context or line anchors."],"tags":["text-editing","file-authoring","string-matching","ambiguous-match","tool-error"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}