FoundationAgents/OpenManus · error · RuntimeError

Failed to create working directory: {e}

Error message

Failed to create working directory: {e}

What it means

AsyncDockerizedTerminal._ensure_workdir runs 'mkdir -p {working_dir}' inside the container via exec_run and wraps any docker APIError in this RuntimeError. mkdir -p rarely fails on its own, so the wrapped APIError usually indicates the exec itself failed: container not running, image lacks a shell (/bin/sh), permission denied at the parent, or an invalid working_dir string.

Source

Thrown at app/sandbox/core/terminal.py:300

        Raises:
            RuntimeError: If initialization fails.
        """
        await self._ensure_workdir()

        self.session = DockerSession(self.container.id)
        await self.session.create(self.working_dir, self.env_vars)

    async def _ensure_workdir(self) -> None:
        """Ensures working directory exists in container.

        Raises:
            RuntimeError: If directory creation fails.
        """
        try:
            await self._exec_simple(f"mkdir -p {self.working_dir}")
        except APIError as e:
            raise RuntimeError(f"Failed to create working directory: {e}")

    async def _exec_simple(self, cmd: str) -> Tuple[int, str]:
        """Executes a simple command using Docker's exec_run.

        Args:
            cmd: Command to execute.

        Returns:
            Tuple of (exit_code, output).
        """
        result = await asyncio.to_thread(
            self.container.exec_run, cmd, environment=self.env_vars
        )
        return result.exit_code, result.output.decode("utf-8")

    async def run_command(self, cmd: str, timeout: Optional[int] = None) -> str:
        """Runs a command in the container with timeout.

View on GitHub (pinned to 52a13f2a57)

Solutions

  1. Check container.status == 'running' (after container.reload()) before creating the terminal.
  2. Quote the path and validate it: f'mkdir -p "{self.working_dir}"' and reject paths with shell metacharacters at construction.
  3. For minimal images, use a base image with coreutils, or create the directory at image build time (WORKDIR /workspace in the Dockerfile).
  4. Read the embedded APIError — 404 means container gone (recreate it), 126/127 means missing binary or permission issue in the image.

Example fix

# before
await self._exec_simple(f"mkdir -p {self.working_dir}")

# after
await self._exec_simple(f'mkdir -p "{self.working_dir}"')
# plus, at the caller:
container.reload()
if container.status != "running":
    raise RuntimeError(f"Container {container.id} is {container.status}; cannot init terminal")
Defensive patterns

Strategy: try-catch

Validate before calling

container.reload()
if container.status != 'running':
    raise RuntimeError(f'cannot init terminal: container is {container.status}')
import re
if re.search(r"[\s'\";&|]", working_dir.strip('/').split('/')[-1]):
    raise ValueError(f'unsafe working_dir: {working_dir!r}')

Try / catch

try:
    async with AsyncDockerizedTerminal(container, working_dir='/workspace') as term:
        ...
except RuntimeError as e:
    if 'Failed to create working directory' in str(e):
        raise RuntimeError('terminal init failed (container dead, read-only fs, or bad path)') from e
    raise

Prevention

When it happens

Trigger: init() called on a stopped/removed container; working_dir containing characters that break the shell line (spaces unquoted, leading -); minimal images (distroless/scratch) with no mkdir binary; read-only filesystem at the target.

Common situations: Container TTL expired before terminal init; distroless images used for sandboxing; working_dir like '/my workspace' passed unquoted; container root filesystem mounted read-only.

Related errors


AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15). Data as JSON: /api/errors/bc5b900193607bce. Report an issue: GitHub.