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

3open issues
3open PRs
16items grouped
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.

These 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

  • PR#40404fix(docker): rewrite DooD auto-mount sources via host_cwd
  • PR#75418fix(docker): resolve sibling bind sources on host
  • PR#80879fix(skills): resolve skill paths to backend-visible locations on remote terminal backends

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #21184 fix(gateway): translate inbound document host paths to container paths for Docker backend (salvage #19048)

    merged to main

    files: gateway/run.py, tools/credential_files.py

    Show 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
Show 2 more
  • #41562 fix(skills): resolve skill directory paths for non-local terminal backends · superseded by another PR → #41561, #41562
  • #50874 fix(docker): translate container paths to host paths for sibling mounts · other
Closed issues · 2
  • Closed#18787[Bug]: Inbound document host paths not translated to container paths under Docker backend
  • Closed#24483Docker sandbox fails with exit 125 when container_persistent=true and credential files are registered
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.00 means 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 Lab

At a glance

Subsystem
environments
Merged PRs
#21184
Closed issues
2
Attempts
7 PRs closed without merging
Fix link checked
7 May 2026

For your agent

The same facts, typed.