Docker backend bind-mount path translation issues
NousResearch/hermes-agent · cluster 18787 · environments
Data as of
6 open items. Fix merged in #21184. Check it covers your case.
The short answer
- Known?
- Yes. 16 related items grouped here, 2 issues already closed.
- Fix event
- A fix was merged to main in PR #21184. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
partially resolved, deciding PR #21184. That is separate from the fix event. - Still open
- 3 issues and 3 PRs.
Next step: read #21184, then check whether your report is one of the 3 still open.
Read #21184Pick up a Lab taskThese items concern incorrect path resolution for bind mounts in Docker-based backends, including credential files, skill directories, cache paths, and document paths that reference container-internal paths instead of host-visible paths. Scenarios covered include sibling containers, Docker-out-of-Docker (DooD), and remote terminal backends.
Open issues3
- Issue#40368[Bug] Docker backend generates container-internal paths for sandbox bind mounts when using host Docker socket (DooD on Unraid)
- Issue#41541${HERMES_SKILL_DIR} resolves to host paths on remote terminal backends
- Issue#50798Sandbox skill + cache bind-mounts are empty under docker-compose self-host (sibling-container bind source uses in-container HERMES_HOME, not the host path)
Open PRs3
Fixes on record
-
#21184 fix(gateway): translate inbound document host paths to container paths for Docker backend (salvage #19048)
files:
gateway/run.py,tools/credential_files.pyShow the diff
-
gateway/run.py@@ -5757,6 +5757,7 @@ async def _prepare_inbound_message_text( if event.media_urls and event.message_type == MessageType.DOCUMENT: import mimetypes as _mimetypes + from tools.credential_files import to_agent_visible_cache_path _TEXT_EXTENSIONS = {".txt", ".md", ".csv", ".log", ".json", ".xml", ".yaml", ".yml", ".toml", ".ini", ".cfg"} for i, path in enumerate(event.media_urls): @@ -5777,16 +5778,21 @@ async def _prepare_inbound_message_text( display_name = parts[2] if len(parts) >= 3 else basename display_name = re.sub(r'[^\w.\- ]', '_', display_name) + # Translate host cache path to in-container path if running under Docker backend. + # This ensures the agent receives a path it can open inside its sandbox, as the + # cache directories are auto-mounted at /root/.hermes/cache/* by get_cache_directory_mounts(). + agent_path = to_agent_visible_cache_path(path) + if mtype.startswith("text/"): context_note = ( f"[The user sent a text document: '{display_name}'. " f"Its content has been included below. " - f"The file is also saved at: {path}]" + f"The file is also saved at: {agent_path}]" ) else: context_note = ( f"[The user sent a document: '{display_name}'. " - f"The file is saved at: {path}. " + f"The file is saved at: {agent_path}. " f"Ask the user what they'd like you to do with it.]" ) message_text = f"{context_note}\n\n{message_text}" -
tools/credential_files.py@@ -374,6 +374,34 @@ def get_cache_directory_mounts( return mounts +def to_agent_visible_cache_path( + host_path: str, + container_base: str = "/root/.hermes", +) -> str: + """Translate a host cache path to its mounted path inside the sandbox. + + Returns the input unchanged if it is not under any auto-mounted cache + directory, or if the active terminal backend does not require path + translation (only Docker for now). + """ + # Only Docker backend requires translation at this time. Other backends + # (Modal, Daytona, Vercel) use different mount semantics and will be + # addressed separately if needed. Backend is identified by TERMINAL_ENV + # (same env var tools/terminal_tool.py reads in _get_environment_config). + if os.environ.get("TERMINAL_ENV", "local") != "docker": + return host_path + + path = Path(host_path) + for mount in get_cache_directory_mounts(container_base=container_base): + host_dir = Path(mount["host_path"]) + try: + rel = path.relative_to(host_dir) + return str(Path(mount["container_path"]) / rel) + except ValueError: + continue + return host_path + + def iter_cache_files( container_base: str = "/root/.hermes", ) -> List[Dict[str, str]]:
-
7 PRs closed without merging
From the close comments: duplicate 2 · superseded by another PR 2 · PR volume cleanup 1 · done elsewhere 1 · other 1
-
#18794 fix(gateway): translate document cache paths for docker · done elsewhere →
#18787 -
#19048 fix(gateway): translate inbound document host paths to container paths for Docker backend · duplicate →
6d1b61d,#18787,#19610 -
#19610 fix(gateway): translate inbound cache paths to container paths for Docker backend · duplicate →
#19048 -
#24555 fix(docker): remove corrupted sandbox dir before credential bind-mount · superseded by another PR →
#24490,#24483 -
#41561 fix(skills): resolve ${HERMES_SKILL_DIR} to backend-visible paths on remote terminal backends · PR volume cleanup →
#41541
Closed issues · 2
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.11: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- environments
- Merged PRs
- #21184
- Closed issues
- 2
- Attempts
- 7 PRs closed without merging
- Fix link checked
- 7 May 2026