{"record":{"id":"8dbd3d3b8cf26397","repo":"vercel/ai","slug":"text-to-replace-was-not-found-in-inputpath","errorCode":null,"errorMessage":"Text to replace was not found in ${inputPath}","messagePattern":"Text to replace was not found in (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/harness-cline/src/cline-remote-ops.ts","lineNumber":241,"sourceCode":"    inputPath: string,\n    oldText: string,\n    newText: string,\n  ): Promise<void> => {\n    const remotePath = resolvePath(inputPath);\n    const resolved = assertWorkspacePath(\n      await resolveExistingSandboxPath({\n        remotePath,\n        inputPath,\n        missingMessage: `File not found: ${inputPath}`,\n      }),\n    );\n    const current = await sandbox.readTextFile({ path: resolved });\n    if (current == null) {\n      throw new Error(`File not found: ${inputPath}`);\n    }\n    const index = current.indexOf(oldText);\n    if (index === -1) {\n      throw new Error(`Text to replace was not found in ${inputPath}`);\n    }\n    const updated = `${current.slice(0, index)}${newText}${current.slice(\n      index + oldText.length,\n    )}`;\n    await writeFile(inputPath, updated);\n  };\n\n  return {\n    resolvePath,\n    readFile,\n    writeFile,\n    editFile,\n\n    async bash(command, input) {\n      const controller = new AbortController();\n      // `input.timeout` is expressed in seconds (the `bash` tool contract),\n      // so convert to milliseconds for `setTimeout`.\n      const timeoutId =","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-cline/src/cline-remote-ops.ts#L223-L259","documentation":"Thrown by editFile when the file was read successfully but current.indexOf(oldText) returns -1 — the oldText snippet does not appear exactly (byte-for-byte) in the file content. The edit is a plain substring replacement, so any difference in whitespace, casing, escaping, or line endings causes this error.","triggerScenarios":"editFile where oldText uses different indentation than the file; CRLF vs LF mismatch; the snippet was already replaced in a previous edit; unicode/escape-sequence differences; stale file content in the agent's context after the file changed.","commonSituations":"LLM agents producing near-miss snippets (tab vs spaces, trimmed trailing whitespace); repeated tool-loop edits applying the same replacement twice; files edited outside the sandbox between the read and the edit; searching across lines with wrong newline style.","solutions":["Re-read the file (ops.readFile) and copy oldText exactly from its current content, preserving whitespace and line endings.","Shorten oldText to a smaller unique substring that is easier to match exactly.","Check for already-applied edits — the target text may already contain newText.","Normalize line endings: if unsure, do the replacement via ops.bash (sed/perl) instead of exact substring matching."],"exampleFix":"// before: snippet from stale memory\nawait ops.editFile('app.ts', 'const x = 1;', 'const x = 2;'); // Text to replace was not found\n\n// after: read fresh content and match exactly\nconst current = await ops.readFile('app.ts');\nif (!current.includes('const x = 1;')) throw new Error('snippet missing');\nawait ops.editFile('app.ts', 'const x = 1;', 'const x = 2;');","handlingStrategy":"validation","validationCode":"async function assertSnippetPresent(ops, p, snippet) {\n  const current = await ops.readFile(p);\n  if (!current.includes(snippet)) {\n    throw new Error(`oldText not present in ${p}; re-read the file and copy exactly`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await ops.editFile(path, oldText, newText);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Text to replace was not found in')) {\n    const current = await ops.readFile(path);\n    if (current.includes(newText)) return; // already applied\n    // retry with a smaller, freshly-copied snippet\n    const anchor = oldText.split('\\n')[0].trim();\n    return ops.editFile(path, anchor, anchor.replace(/old/g, 'new'));\n  }\n  throw e;\n}","preventionTips":["Always read the file immediately before editing; never reuse snippets from stale context.","Copy oldText byte-for-byte including indentation and line endings.","Prefer short unique anchors over long multi-line snippets.","Check whether the edit was already applied before retrying.","For whitespace-sensitive files, edit via bash (sed/perl) instead of exact matching."],"tags":["edit","filesystem","text-match"],"backgroundTag":"edit-match-not-found","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}