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

  1. Re-read the file and rebuild old_string from its current exact content, then retry the patch.
  2. If the edit was already applied by another writer, verify the desired end state before re-patching.
  3. Reduce old_string to a smaller unique anchor line to make matching robust.
  4. 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

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


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/67913437bed02db7. Report an issue: GitHub.