NousResearch/hermes-agent · error · ValueError
{error or 'Could not find match for old_string in {path}'}
Error message
{error or 'Could not find match for old_string in {path}'} What it means
Raised by _proposal_for_patch_replace after running tools.fuzzy_match.fuzzy_find_and_replace on the file's current content: the matcher reported an error, or found zero occurrences of old_string. Hermes' patch pipeline uses fuzzy matching to tolerate whitespace drift, so reaching this error means even fuzzy matching could not anchor old_string in the file — typically because the file content diverged from what the caller expected (already edited, different version, old_string from an older read).
Source
Thrown at acp_adapter/edit_approval.py:120
old_string = arguments.get("old_string")
new_string = arguments.get("new_string")
if old_string is None or new_string is None:
raise ValueError("old_string and new_string required")
old_text = _read_text_if_exists(path)
if old_text is None:
raise ValueError(f"Failed to read file: {path}")
from tools.fuzzy_match import fuzzy_find_and_replace
new_text, match_count, _strategy, error = fuzzy_find_and_replace(
old_text,
str(old_string),
str(new_string),
bool(arguments.get("replace_all", False)),
)
if error or match_count == 0:
raise ValueError(error or f"Could not find match for old_string in {path}")
return EditProposal(
tool_name="patch",
path=path,
old_text=old_text,
new_text=new_text,
arguments=dict(arguments),
)
def _extract_v4a_patch_paths(patch_body: str) -> list[str]:
paths: list[str] = []
for match in re.finditer(
r'^\*\*\*\s+(?:Update|Add|Delete)\s+File:\s*(.+)$',
patch_body,
re.MULTILINE,
):
path = match.group(1).strip()View on GitHub (pinned to c896c09c42)
Solutions
- Re-read the file and rebuild old_string from its current exact content, then retry the patch.
- If the edit was already applied by another writer, verify the desired end state before re-patching.
- Reduce old_string to a smaller unique anchor line to make matching robust.
- For replace_all scenarios, confirm the target string actually occurs (search first).
Example fix
# before
if error or match_count == 0:
raise ValueError(error or f"Could not find match for old_string in {path}")
# after — report near-misses so the caller can self-correct
if error or match_count == 0:
best = fuzzy_best_ratio(old_text, str(old_string))
hint = f" (closest similarity {best:.2f})" if best else ""
raise ValueError(error or f"Could not find match for old_string in {path}{hint}; re-read the file and retry") Defensive patterns
Strategy: try-catch
Validate before calling
from pathlib import Path
current = Path(path).expanduser().read_text(encoding='utf-8', errors='replace')
if old_string not in current:
# exact anchor absent — re-read and rebuild old_string before patching
raise SystemExit('stale old_string; refresh context') Type guard
def old_string_present(text: str, old_string: str) -> bool:
return old_string in text Try / catch
try:
proposal = _proposal_for_patch_replace(arguments)
except ValueError as err:
if 'Could not find match' in str(err):
fresh = Path(path).expanduser().read_text(encoding='utf-8', errors='replace')
# rebuild old_string from `fresh` and retry once; surface to agent on second failure
else:
raise Prevention
- Always re-read the file immediately before constructing old_string
- Prefer short unique anchor lines over long multi-line snippets
- Fail fast on stale context instead of patching from memory
- Use replace_all only after confirming the string occurs
When it happens
Trigger: A patch whose old_string does not appear in the current file: the file was modified since the agent last read it, old_string was hand-typed with different indentation/quotes, replace_all=False with an old_string that matches nothing, or the fuzzy matcher returned a strategy error (e.g. ambiguous multi-match where one was required).
Common situations: Concurrent edits (two agents or agent+human editing the same file), stale context after context compression, copying old_string from a different branch, tab-vs-space drift beyond fuzzy tolerance.
Related errors
- old_string and new_string required
- Failed to read file: {path}
- patch content required
- no file paths found in V4A patch
- Cannot edit non-file path: {path}
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/67913437bed02db7.
Report an issue: GitHub.