FoundationAgents/OpenManus · error · ToolError
No replacement was performed, old_str `{old_str}` did not ap
Error message
No replacement was performed, old_str `{old_str}` did not appear verbatim in {path}. What it means
Thrown by the str_replace_editor tool when a str_replace operation finds zero occurrences of old_str in the target file. The tool reads the file, expands tabs on both content and arguments, and counts occurrences; an exact verbatim substring match is required before any edit is attempted. A zero count aborts the edit entirely — nothing is written.
Source
Thrown at app/tool/str_replace_editor.py:300
)
async def str_replace(
self,
path: PathLike,
old_str: str,
new_str: Optional[str] = None,
operator: FileOperator = None,
) -> CLIResult:
"""Replace a unique string in a file with a new string."""
# Read file content and expand tabs
file_content = (await operator.read_file(path)).expandtabs()
old_str = old_str.expandtabs()
new_str = new_str.expandtabs() if new_str is not None else ""
# Check if old_str is unique in the file
occurrences = file_content.count(old_str)
if occurrences == 0:
raise ToolError(
f"No replacement was performed, old_str `{old_str}` did not appear verbatim in {path}."
)
elif occurrences > 1:
# Find line numbers of occurrences
file_content_lines = file_content.split("\n")
lines = [
idx + 1
for idx, line in enumerate(file_content_lines)
if old_str in line
]
raise ToolError(
f"No replacement was performed. Multiple occurrences of old_str `{old_str}` "
f"in lines {lines}. Please ensure it is unique"
)
# Replace old_str with new_str
new_file_content = file_content.replace(old_str, new_str)
View on GitHub (pinned to 52a13f2a57)
Solutions
- Re-read the file (view command) at the current path and copy old_str verbatim, including exact leading whitespace and line breaks.
- Verify the path is correct — editing a different file than the one displayed is a frequent cause.
- Check for line-ending or encoding mismatches; normalize the editor to LF if the file uses LF.
- Use a longer, more distinctive snippet as old_str to guarantee an exact match.
- If the string may have drifted, fall back to a write/insert operation instead of str_replace.
Example fix
// before
await editor.str_replace('app/main.py', old_str='def run():\n pass', new_str='def run():\n return 0') // indentation mismatch -> error
// after
await editor.view('app/main.py') // confirm exact text
await editor.str_replace('app/main.py', old_str='def run():\n\t pass', new_str='def run():\n\t return 0') // copied verbatim from file Defensive patterns
Strategy: validation
Validate before calling
content = await operator.read_file(path)
if old_str.expandtabs() not in content.expandtabs():
refreshed = await editor.view(path) # re-read and re-derive old_str
# rebuild old_str from refreshed content or abort before calling str_replace Type guard
def is_exact_snippet(content: str, old_str: str) -> bool:
return content.expandtabs().count(old_str.expandtabs()) == 1 Try / catch
try:
await editor.str_replace(path, old_str, new_str)
except ToolError as e:
if 'did not appear verbatim' in str(e):
content = await editor.view(path)
# re-derive old_str from the fresh content and retry once
else:
raise Prevention
- Always view/read the file immediately before editing and copy old_str verbatim from that read.
- Normalize line endings and tabs in your pipeline before constructing old_str (the tool expands tabs but nothing else).
- Never build old_str from memory or a cached snapshot of the file.
When it happens
Trigger: Calling str_replace with an old_str that does not exactly match file content: wrong indentation, tabs vs spaces (note tabs are expanded before matching, so an 8-space vs tab mismatch is normalized but other whitespace differences are not), trailing whitespace, line-ending differences (CRLF vs LF), or the file having changed since it was last read.
Common situations: Agent/tool pipelines that reuse a cached file snapshot then edit after another writer changed the file; copy-pasting old_str from a rendered view that altered whitespace; assuming fuzzy or regex matching when the tool only does literal substring matching.
Related errors
- No replacement was performed. Multiple occurrences of old_st
- No edit history found for {path}.
- Invalid `insert_line` parameter: {insert_line}. It should be
AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15).
Data as JSON: /api/errors/ce7c162622c30f05.
Report an issue: GitHub.