NousResearch/hermes-agent · error · ValueError
old_string and new_string required
Error message
old_string and new_string required
What it means
Raised by _proposal_for_patch_replace when either 'old_string' or 'new_string' is missing (None) from the patch tool-call arguments. Both are needed to render an approval diff and to run fuzzy_find_and_replace. Empty strings are allowed (deletion/insertion edge cases); only absence triggers the error.
Source
Thrown at acp_adapter/edit_approval.py:105
if content is None:
raise ValueError("content required")
return EditProposal(
tool_name="write_file",
path=path,
old_text=_read_text_if_exists(path),
new_text=str(content),
arguments=dict(arguments),
)
def _proposal_for_patch_replace(arguments: dict[str, Any]) -> EditProposal:
path = str(arguments.get("path") or "")
if not path:
raise ValueError("path required")
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",View on GitHub (pinned to c896c09c42)
Solutions
- Always send both old_string and new_string, using '' for the empty side (deletion or insertion).
- Normalize field aliases at the ACP boundary if clients use different names.
- Fix the agent's tool description to state both fields are required and may be empty strings.
- Map null to '' for the intentionally-empty side before validation if your protocol distinguishes null from ''.
Example fix
# before
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")
# after — accept explicit null as empty (delete/insert) semantics
old_string = arguments.get("old_string")
new_string = arguments.get("new_string")
if old_string is None and new_string is None:
raise ValueError("old_string and new_string required")
old_string = old_string or ""
new_string = new_string or "" Defensive patterns
Strategy: validation
Validate before calling
old_string = arguments.get("old_string")
new_string = arguments.get("new_string")
if old_string is None or new_string is None:
return invalid_params("patch requires both old_string and new_string (use '' for empty)") Type guard
def has_patch_strings(args: dict[str, Any]) -> bool:
return args.get("old_string") is not None and args.get("new_string") is not None Try / catch
try:
proposal = _proposal_for_patch_replace(arguments)
except ValueError as err:
return {"error": {"code": -32602, "message": str(err)}} Prevention
- State in the tool description: both fields required, empty string legal for delete/insert
- Map null to '' explicitly if your producer distinguishes them
- Validate at the boundary so agents get actionable invalid-params errors
When it happens
Trigger: A patch call where the agent supplied old_string but omitted new_string (intending deletion via empty string but sending null instead), or vice versa; schema mismatches renaming the fields to find/replace.
Common situations: LLM agents emitting {path, old_string} for deletes with new_string: null; clients using search/replace naming from other ecosystems (find/replace, match/replacement).
Related errors
- patch content required
- no file paths found in V4A patch
- Cannot edit non-file path: {path}
- path required
- content required
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/7c7744a49371cb41.
Report an issue: GitHub.