NousResearch/hermes-agent · error · ValueError
Failed to read file: {path}
Error message
Failed to read file: {path} What it means
Raised by _proposal_for_patch_replace when _read_text_if_exists(path) returns None — meaning Path(path).expanduser() does not exist. A search/replace patch can only apply to an existing file (unlike write_file, which can create one), so the proposal builder refuses to continue when the target is absent. This fires before the fuzzy matcher, distinguishing 'file missing' from 'match not found'.
Source
Thrown at acp_adapter/edit_approval.py:109
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",
path=path,
old_text=old_text,
new_text=new_text,
arguments=dict(arguments),View on GitHub (pinned to c896c09c42)
Solutions
- Verify the file exists from the adapter's working directory; correct the path or create the file with write_file first.
- Use absolute paths in patch calls to avoid cwd-relative mismatches.
- If the file was deleted intentionally, recreate it with write_file before patching.
- Catch this ValueError in the dispatcher and reply 'file not found' so the agent can self-correct.
Example fix
# before
old_text = _read_text_if_exists(path)
if old_text is None:
raise ValueError(f"Failed to read file: {path}")
# after — distinguish missing vs unreadable for the agent
old_text = _read_text_if_exists(path)
if old_text is None:
if not Path(path).expanduser().exists():
raise ValueError(f"File does not exist: {path}")
raise ValueError(f"Failed to read file: {path}") Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
if not Path(path).expanduser().exists():
return error_response(f"File not found: {path} — create it with write_file first or fix the path") Type guard
def file_exists(path: str) -> bool:
return Path(path).expanduser().is_file() Try / catch
try:
proposal = _proposal_for_patch_replace(arguments)
except ValueError as err:
if "Failed to read file" in str(err):
# instruct the agent to re-check the path or use write_file to create
return {"error": {"code": -32602, "message": str(err)}}
raise Prevention
- Use absolute paths in patch calls to avoid cwd-relative misses
- Create new files with write_file, never patch
- Re-verify existence after long-running turns where files may have changed
When it happens
Trigger: A patch call targeting a file that was never created, was deleted, or whose path is wrong (typo, wrong relative root, ~ not expanded by the caller — note expanduser() here handles it, but a wrong cwd-relative path still misses).
Common situations: Agents patching files by remembered paths after the files were renamed; relative paths resolved from a different working directory than the agent assumed; first-edit attempts on files the agent intended to create with patch instead of write_file.
Related errors
- Cannot edit non-file path: {path}
- old_string and new_string required
- {error or 'Could not find match for old_string in {path}'}
- patch content required
- no file paths found in V4A patch
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/4fce72acbd724885.
Report an issue: GitHub.