{"record":{"id":"3dc23cbfcfde1446","repo":"agentscope-ai/agentscope","slug":"host-workdir-must-be-a-directory","errorCode":null,"errorMessage":"host_workdir must be a directory.","messagePattern":"host_workdir must be a directory\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/agentscope/workspace/_bubblewrap/_bubblewrap_workspace.py","lineNumber":205,"sourceCode":"        \"\"\"Whether the workspace files survive ``close``.\"\"\"\n        return self._host_workdir_input is not None\n\n    async def _provision_backend(self) -> None:\n        \"\"\"Validate Bubblewrap availability and bind the backend.\"\"\"\n        if not sys.platform.startswith(\"linux\"):\n            raise RuntimeError(\"BubblewrapWorkspace requires Linux.\")\n        if shutil.which(\"bwrap\") is None:\n            raise RuntimeError(\"BubblewrapWorkspace requires 'bwrap' on PATH.\")\n        await self._probe_bubblewrap()\n        if self._host_workdir_input is None:\n            self._owned_workdir = tempfile.TemporaryDirectory()\n            self.host_workdir = self._owned_workdir.name\n        else:\n            self.host_workdir = os.path.abspath(self._host_workdir_input)\n        workdir_created = not os.path.lexists(self.host_workdir)\n        os.makedirs(self.host_workdir, mode=0o700, exist_ok=True)\n        if not os.path.isdir(self.host_workdir):\n            raise ValueError(\"host_workdir must be a directory.\")\n        if workdir_created:\n            os.chmod(self.host_workdir, 0o700)\n\n        if (\n            self._host_workdir_input is None\n            and self._host_cache_dir_input is None\n        ):\n            self._owned_cache_dir = tempfile.TemporaryDirectory(\n                prefix=\"agentscope-bwrap-cache-\",\n            )\n            self._host_cache_dir = self._owned_cache_dir.name\n        else:\n            self._host_cache_dir = self._resolve_host_cache_dir()\n        self._tmpdir = tempfile.TemporaryDirectory()\n        self._backend = BubblewrapBackend(\n            host_workdir=self.host_workdir,\n            host_tmpdir=self._tmpdir.name,\n            host_cache_dir=self._host_cache_dir,","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/workspace/_bubblewrap/_bubblewrap_workspace.py#L187-L223","documentation":"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.","triggerScenarios":"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.","commonSituations":"Pointing host_workdir at an existing file; leftover artifact (a file) at the intended workspace path; permission issues causing makedirs to partially fail.","solutions":["Check the path: ls -l <host_workdir> and remove/rename the conflicting file","Point host_workdir to a fresh or genuinely directory path","Ensure parent directories are writable so makedirs(0o700) succeeds"],"exampleFix":"# before\nws = BubblewrapWorkspace(host_workdir=\"/tmp/ws\")  # /tmp/ws is a file\n# after\nimport os\nif os.path.lexists(\"/tmp/ws\") and not os.path.isdir(\"/tmp/ws\"):\n    os.remove(\"/tmp/ws\")\nws = BubblewrapWorkspace(host_workdir=\"/tmp/ws\")","handlingStrategy":"validation","validationCode":"import os\np = cfg_host_workdir\nif os.path.lexists(p) and not os.path.isdir(p):\n    raise ValueError(f\"host_workdir path {p} is not a directory\")","typeGuard":"def is_valid_workdir(p: str) -> bool:\n    return not os.path.lexists(p) or os.path.isdir(p) and not os.path.islink(p)","tryCatchPattern":"try:\n    ws = await BubblewrapWorkspace.create(...)\nexcept ValueError as e:\n    if \"host_workdir\" in str(e):\n        # clean conflicting path and retry once","preventionTips":["Pre-validate workspace paths before constructing the workspace","Never point host_workdir at files created by other tools"],"tags":["bubblewrap","sandbox","filesystem","workspace","path-validation"],"backgroundTag":"path-exists-but-wrong-type","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}