agentscope-ai/agentscope · error · ValueError

host_workdir must be a directory.

Error message

host_workdir must be a directory.

What it means

BubblewrapWorkspace validates that the configured host workdir path is a directory after creating it. If the path exists but is not a directory (e.g. it is a regular file), provisioning fails immediately. This guards the sandbox's bind-mounted workspace root.

Source

Thrown at src/agentscope/workspace/_bubblewrap/_bubblewrap_workspace.py:205

        """Whether the workspace files survive ``close``."""
        return self._host_workdir_input is not None

    async def _provision_backend(self) -> None:
        """Validate Bubblewrap availability and bind the backend."""
        if not sys.platform.startswith("linux"):
            raise RuntimeError("BubblewrapWorkspace requires Linux.")
        if shutil.which("bwrap") is None:
            raise RuntimeError("BubblewrapWorkspace requires 'bwrap' on PATH.")
        await self._probe_bubblewrap()
        if self._host_workdir_input is None:
            self._owned_workdir = tempfile.TemporaryDirectory()
            self.host_workdir = self._owned_workdir.name
        else:
            self.host_workdir = os.path.abspath(self._host_workdir_input)
        workdir_created = not os.path.lexists(self.host_workdir)
        os.makedirs(self.host_workdir, mode=0o700, exist_ok=True)
        if not os.path.isdir(self.host_workdir):
            raise ValueError("host_workdir must be a directory.")
        if workdir_created:
            os.chmod(self.host_workdir, 0o700)

        if (
            self._host_workdir_input is None
            and self._host_cache_dir_input is None
        ):
            self._owned_cache_dir = tempfile.TemporaryDirectory(
                prefix="agentscope-bwrap-cache-",
            )
            self._host_cache_dir = self._owned_cache_dir.name
        else:
            self._host_cache_dir = self._resolve_host_cache_dir()
        self._tmpdir = tempfile.TemporaryDirectory()
        self._backend = BubblewrapBackend(
            host_workdir=self.host_workdir,
            host_tmpdir=self._tmpdir.name,
            host_cache_dir=self._host_cache_dir,

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Check the path: ls -l <host_workdir> and remove/rename the conflicting file
  2. Point host_workdir to a fresh or genuinely directory path
  3. Ensure parent directories are writable so makedirs(0o700) succeeds

Example fix

# before
ws = BubblewrapWorkspace(host_workdir="/tmp/ws")  # /tmp/ws is a file
# after
import os
if os.path.lexists("/tmp/ws") and not os.path.isdir("/tmp/ws"):
    os.remove("/tmp/ws")
ws = BubblewrapWorkspace(host_workdir="/tmp/ws")
Defensive patterns

Strategy: validation

Validate before calling

import os
p = cfg_host_workdir
if os.path.lexists(p) and not os.path.isdir(p):
    raise ValueError(f"host_workdir path {p} is not a directory")

Type guard

def is_valid_workdir(p: str) -> bool:
    return not os.path.lexists(p) or os.path.isdir(p) and not os.path.islink(p)

Try / catch

try:
    ws = await BubblewrapWorkspace.create(...)
except ValueError as e:
    if "host_workdir" in str(e):
        # clean conflicting path and retry once

Prevention

When it happens

Trigger: Calling BubblewrapWorkspace provisioning with a host_workdir that already exists as a file, fifo, or a path where makedirs raced/failed; also when makedirs silently succeeds on a path that lexists as a file with exist_ok semantics differing.

Common situations: Pointing host_workdir at an existing file; leftover artifact (a file) at the intended workspace path; permission issues causing makedirs to partially fail.

Related errors


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