agentscope-ai/agentscope · error · ValueError

{left_name} must not overlap {right_name}.

Error message

{left_name} must not overlap {right_name}.

What it means

Raised by BubblewrapBackend.__init__ when two configured host mount sources (e.g. host_workdir, host_tmpdir, host_cache_dir) resolve to overlapping real paths. Because each directory is bind-mounted separately into the bwrap sandbox, nested mounts would conflict, so the constructor rejects them up front.

Source

Thrown at src/agentscope/workspace/_bubblewrap/_bubblewrap_backend.py:100

        )
        mount_sources: list[tuple[str, str]] = [
            ("host_workdir", self._host_workdir),
            ("host_tmpdir", self._host_tmpdir),
        ]
        self._host_cache_dir: str | None = None
        self._host_cache_identity: tuple[int, int] | None = None
        cache_dir: str | None = None
        if host_cache_dir is not None:
            cache_dir = os.path.abspath(host_cache_dir)
            if os.path.lexists(cache_dir) and os.path.islink(cache_dir):
                raise ValueError("host_cache_dir must not be a symbolic link.")
            cache_realpath = os.path.realpath(cache_dir)
            self._host_cache_dir = cache_realpath
            mount_sources.append(("host_cache_dir", cache_realpath))
        for index, (left_name, left_path) in enumerate(mount_sources):
            for right_name, right_path in mount_sources[index + 1 :]:
                if self._paths_overlap(left_path, right_path):
                    raise ValueError(
                        f"{left_name} must not overlap {right_name}.",
                    )
        if cache_dir is not None:
            cache_created = not os.path.lexists(cache_dir)
            os.makedirs(cache_dir, mode=0o700, exist_ok=True)
            if cache_created:
                os.chmod(cache_dir, 0o700)
            if not os.path.isdir(cache_dir):
                raise ValueError("host_cache_dir must be a directory.")
            assert self._host_cache_dir is not None
            self._host_cache_identity = self._directory_identity(
                self._host_cache_dir,
                label="host_cache_dir",
            )
        self._workdir = workdir
        self._share_net = share_net
        self._env = dict(env or {})

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Point each of host_workdir, host_tmpdir, and host_cache_dir at disjoint directories (e.g. /data/ws and /var/cache/ws)
  2. If you want one shared tree, drop the redundant option (set cache_dir=None) instead of nesting it
  3. Check with os.path.realpath before constructing that no path is a prefix of another

Example fix

# before
ws = BubblewrapWorkspace(host_workdir='/data/app', host_cache_dir='/data/app/cache')
# after
ws = BubblewrapWorkspace(host_workdir='/data/app', host_cache_dir='/var/cache/app')
Defensive patterns

Strategy: validation

Validate before calling

import os
real = {name: os.path.realpath(p) for name, p in [('workdir', wd), ('tmpdir', td), ('cache', cd)] if p}
paths = list(real.values())
for i, a in enumerate(paths):
    for b in paths[i+1:]:
        assert not (a == b or a.startswith(b + os.sep) or b.startswith(a + os.sep)), 'overlapping mounts'

Type guard

null

Try / catch

try:
    backend = BubblewrapBackend(...)
except ValueError as e:
    if 'must not overlap' in str(e):
        # pick disjoint directories and retry

Prevention

When it happens

Trigger: Passing host_cache_dir that is equal to, a parent of, or a child of host_workdir or host_tmpdir; any pair of mount source directories whose realpath contains the other.

Common situations: Setting cache_dir inside the workspace directory, reusing the same temp dir for workdir and cache, or pointing multiple config options at ~/project.

Related errors


AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28). Data as JSON: /api/errors/5953a15da0dc1fa6. Report an issue: GitHub.