{"record":{"id":"a283ab949b3ee3e3","repo":"NousResearch/hermes-agent","slug":"path-required","errorCode":null,"errorMessage":"path required","messagePattern":"path required","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"acp_adapter/edit_approval.py","lineNumber":85,"sourceCode":"\n\ndef get_edit_approval_requester() -> EditApprovalRequester | None:\n    return _EDIT_APPROVAL_REQUESTER.get()\n\n\ndef _read_text_if_exists(path: str) -> str | None:\n    p = Path(path).expanduser()\n    if not p.exists():\n        return None\n    if not p.is_file():\n        raise OSError(f\"Cannot edit non-file path: {path}\")\n    return p.read_text(encoding=\"utf-8\", errors=\"replace\")\n\n\ndef _proposal_for_write_file(arguments: dict[str, Any]) -> EditProposal:\n    path = str(arguments.get(\"path\") or \"\")\n    if not path:\n        raise ValueError(\"path required\")\n    content = arguments.get(\"content\")\n    if content is None:\n        raise ValueError(\"content required\")\n    return EditProposal(\n        tool_name=\"write_file\",\n        path=path,\n        old_text=_read_text_if_exists(path),\n        new_text=str(content),\n        arguments=dict(arguments),\n    )\n\n\ndef _proposal_for_patch_replace(arguments: dict[str, Any]) -> EditProposal:\n    path = str(arguments.get(\"path\") or \"\")\n    if not path:\n        raise ValueError(\"path required\")\n    old_string = arguments.get(\"old_string\")\n    new_string = arguments.get(\"new_string\")","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/acp_adapter/edit_approval.py#L67-L103","documentation":"Raised by _proposal_for_write_file in the ACP adapter when building an edit-approval proposal for a write_file tool call whose arguments contain no non-empty 'path' string. The proposal needs a target file to show the user a diff, so an empty/missing path is rejected before any filesystem access. It indicates the client sent a malformed tool-call payload, not a filesystem problem.","triggerScenarios":"An ACP client (VS Code/Zed/JetBrains extension or an agent behind it) emits a write_file call with path omitted, empty string, or None (which str()s to '').","commonSituations":"Version mismatch between the editor extension and the tool schema; an LLM agent omitting required fields; JSON payloads where path was nested under the wrong key.","solutions":["Fix the caller to always send a non-empty absolute 'path' in write_file arguments.","Align editor extension and ACP adapter versions so the tool schema matches.","If an agent produced the call, tighten its tool schema to mark path as required.","Catch ValueError in the ACP dispatcher and return it as an invalid-params error to the client."],"exampleFix":"# before\npath = str(arguments.get(\"path\") or \"\")\nif not path:\n    raise ValueError(\"path required\")\n\n# after — validate the raw type too (reject path: 123 -> \"123\")\nraw_path = arguments.get(\"path\")\nif not isinstance(raw_path, str) or not raw_path.strip():\n    raise ValueError(\"path required (non-empty string)\")\npath = raw_path","handlingStrategy":"validation","validationCode":"raw = arguments.get(\"path\")\nif not isinstance(raw, str) or not raw.strip():\n    return invalid_params(\"write_file requires a non-empty 'path' string\")","typeGuard":"def has_valid_path(args: dict[str, Any]) -> bool:\n    p = args.get(\"path\")\n    return isinstance(p, str) and bool(p.strip())","tryCatchPattern":"try:\n    proposal = _proposal_for_write_file(arguments)\nexcept ValueError as err:\n    return {\"error\": {\"code\": -32602, \"message\": str(err)}}  # invalid params -> client retries","preventionTips":["Mark 'path' required in the tool schema exposed to agents","Validate argument shape at the ACP boundary before proposal building","Log the raw arguments dict (minus content) when validation fails to catch schema drift"],"tags":["acp","editor-integration","validation","tool-schema","python"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}