CherryHQ/cherry-studio · error · Error
old_string not found in content
Error message
old_string not found in content
What it means
Thrown by replaceWithFuzzyMatch when none of the nine replacers (Simple, LineTrimmed, BlockAnchor, WhitespaceNormalized, IndentationFlexible, EscapeNormalized, TrimmedBoundary, ContextAware, MultiOccurrence) yields any substring that content.indexOf can locate. The variable notFound stays true through the whole ALL_REPLACERS loop, meaning the old_string is absent from the content beyond what fuzzy matching can recover.
Source
Thrown at src/main/ai/mcp/servers/filesystem/types.ts:545
let notFound = true
for (const replacer of ALL_REPLACERS) {
for (const search of replacer(content, oldString)) {
const index = content.indexOf(search)
if (index === -1) continue
notFound = false
if (replaceAll) {
return content.replaceAll(search, newString)
}
const lastIndex = content.lastIndexOf(search)
if (index !== lastIndex) continue
return content.substring(0, index) + newString + content.substring(index + search.length)
}
}
if (notFound) {
throw new Error('old_string not found in content')
}
throw new Error(
'Found multiple matches for old_string. Provide more surrounding lines in old_string to identify the correct match.'
)
}
// ============================================================================
// Binary File Detection
// ============================================================================
// Check if a file is likely binary
export async function isBinaryFile(filePath: string): Promise<boolean> {
try {
const buffer = Buffer.alloc(4096)
const fd = await fs.open(filePath, 'r')
const { bytesRead } = await fd.read(buffer, 0, buffer.length, 0)
await fd.close()
View on GitHub (pinned to 726446b54c)
Solutions
- Re-read the file to get current content, then copy old_string verbatim from that read.
- Normalize line endings (CRLF -> LF) on both content and old_string before editing.
- Shorten old_string to a unique anchor that is more likely to survive the fuzzy replacers, or expand it with exact surrounding context.
- Confirm you are editing the same file path that was read (no path mismatch).
Example fix
// before replaceWithFuzzyMatch(staleContent, 'const x = 1;', 'const x = 2;') // throws: old_string not found // after const fresh = await fs.readFile(target, 'utf-8') replaceWithFuzzyMatch(fresh, 'const x = 1;', 'const x = 2;')
Defensive patterns
Strategy: validation
Validate before calling
function canFind(content: string, oldString: string): boolean {
// cheapest signal before invoking fuzzy matching
return content.includes(oldString) ||
content.split('\n').some(l => l.trim() === oldString.trim())
} Try / catch
try {
replaceWithFuzzyMatch(content, oldString, newString)
} catch (e) {
if (e instanceof Error && e.message === 'old_string not found in content') {
// re-read the file and rebuild old_string from the fresh content
} else throw e
} Prevention
- Always re-read the file immediately before editing; never edit against a cached snapshot.
- Normalize line endings (CRLF -> LF) on both sides before editing.
- Copy old_string verbatim from the most recent read output, including exact whitespace.
- Prefer minimal unique anchors expanded with surrounding context over large guess blocks.
When it happens
Trigger: Editing a file with old_string that no longer matches after the file changed on disk; old_string copied from a different file; content was reloaded from a stale cache; old_string includes lines that were already edited in a prior step of the same session.
Common situations: Multi-step edit where step 1 changed the region step 2 targets; LLM hallucinated old_string from memory rather than a fresh read; trailing whitespace/line-ending (CRLF vs LF) differences beyond what the normalization replacers cover (e.g. BOM, mixed encodings); file replaced wholesale between read and edit.
Related errors
- old_string and new_string must be different
- Found multiple matches for old_string. Provide more surround
- Path is not a file: ${filePath}
- File not found: ${filePath}
- Cannot read binary file: ${filePath}
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/2138d77b9b56a2e7.
Report an issue: GitHub.