{"record":{"id":"7418eaca6531cd73","repo":"NousResearch/hermes-agent","slug":"acp-file-system-paths-must-be-absolute","errorCode":null,"errorMessage":"ACP file-system paths must be absolute.","messagePattern":"ACP file-system paths must be absolute\\.","errorType":"exception","errorClass":"PermissionError","httpStatus":null,"severity":"error","filePath":"agent/copilot_acp_client.py","lineNumber":373,"sourceCode":"\n    parts: list[str] = []\n    cursor = 0\n    for start, end in merged:\n        if cursor < start:\n            parts.append(text[cursor:start])\n        cursor = max(cursor, end)\n    if cursor < len(text):\n        parts.append(text[cursor:])\n\n    cleaned = \"\\n\".join(p.strip() for p in parts if p and p.strip()).strip()\n    return extracted, cleaned\n\n\n\ndef _ensure_path_within_cwd(path_text: str, cwd: str) -> Path:\n    candidate = Path(path_text)\n    if not candidate.is_absolute():\n        raise PermissionError(\"ACP file-system paths must be absolute.\")\n    resolved = candidate.resolve()\n    root = Path(cwd).resolve()\n    try:\n        resolved.relative_to(root)\n    except ValueError as exc:\n        raise PermissionError(f\"Path '{resolved}' is outside the session cwd '{root}'.\") from exc\n    return resolved\n\n\nclass _ACPChatCompletions:\n    def __init__(self, client: \"CopilotACPClient\"):\n        self._client = client\n\n    def create(self, **kwargs: Any) -> Any:\n        return self._client._create_chat_completion(**kwargs)\n\n\nclass _ACPChatNamespace:","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/agent/copilot_acp_client.py#L355-L391","documentation":"The ACP (Agent Client Protocol) file-system bridge in agent/copilot_acp_client.py received a relative path in an fs/read_text_file or fs/write_text_file request. _ensure_path_within_cwd requires absolute paths because the ACP peer (GitHub Copilot CLI) may have a different process cwd, making relative paths ambiguous and unsafe to resolve.","triggerScenarios":"A JSON-RPC fs request from the Copilot ACP process whose params.path is relative (e.g. 'src/main.py'). Raised before any resolution — Path(path_text).is_absolute() is false.","commonSituations":"Version skew where an older/newer Copilot CLI emits relative paths; a custom HERMES_COPILOT_ACP_COMMAND binary that does not follow the ACP fs path convention. Not typically user-triggerable directly.","solutions":["Update GitHub Copilot CLI to the current version (npm install -g @github/copilot) so it sends absolute paths.","If using a custom ACP command via HERMES_COPILOT_ACP_COMMAND, ensure it emits absolute paths in fs methods.","Report to the Hermes maintainers if a current Copilot CLI still sends relative paths."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef valid_acp_fs_path(path_text: str) -> bool:\n    return Path(path_text).is_absolute()","typeGuard":null,"tryCatchPattern":"try:\n    handle_fs_request(params)\nexcept PermissionError as e:\n    if \"must be absolute\" in str(e):\n        # normalize to absolute relative to cwd and retry once\n        ...","preventionTips":["Always emit absolute paths in ACP fs methods","Keep the Copilot CLI current so it follows the path convention","When shimming ACP, resolve paths against the session cwd before sending"],"tags":["acp","copilot","path-validation","protocol"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}