FoundationAgents/OpenManus · error · RuntimeError

Terminal not initialized

Error message

Terminal not initialized

What it means

AsyncDockerizedTerminal.execute() delegates to an internal DockerSession created in init(); calling execute() before init() (or after a failed init) hits this guard. The class is a lifecycle wrapper: init() creates the session, and the async context manager (__aenter__) is the supported way to guarantee ordering.

Source

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

            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.

        Args:
            cmd: Shell command to execute.
            timeout: Maximum execution time in seconds.

        Returns:
            Command output as string.

        Raises:
            RuntimeError: If terminal not initialized.
        """
        if not self.session:
            raise RuntimeError("Terminal not initialized")

        return await self.session.execute(cmd, timeout=timeout or self.default_timeout)

    async def close(self) -> None:
        """Closes the terminal session."""
        if self.session:
            await self.session.close()

    async def __aenter__(self) -> "AsyncDockerizedTerminal":
        """Async context manager entry."""
        await self.init()
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
        """Async context manager exit."""
        await self.close()

View on GitHub (pinned to 52a13f2a57)

Solutions

  1. Use the context manager: 'async with AsyncDockerizedTerminal(container, working_dir="/workspace") as term: await term.execute(...)' — __aenter__ calls init().
  2. Or call 'await term.init()' explicitly and treat any exception there as fatal; do not call execute() afterwards.
  3. Check 'term.session is not None' as a cheap pre-condition in calling code that receives a terminal from elsewhere.
  4. Close and rebuild the terminal after any init failure instead of reusing the half-initialized object.

Example fix

# before
term = AsyncDockerizedTerminal(container)
out = await term.execute("ls")  # RuntimeError: Terminal not initialized

# after
async with AsyncDockerizedTerminal(container) as term:
    out = await term.execute("ls")
Defensive patterns

Strategy: validation

Validate before calling

if term.session is None:
    await term.init()
assert term.session is not None

Type guard

async def ensure_terminal(term: AsyncDockerizedTerminal) -> AsyncDockerizedTerminal:
    if term.session is None:
        await term.init()
    return term

Try / catch

try:
    out = await term.execute(cmd)
except RuntimeError as e:
    if 'Terminal not initialized' in str(e):
        async with AsyncDockerizedTerminal(term.container, term.working_dir, term.env_vars) as term2:
            out = await term2.execute(cmd)
    else:
        raise

Prevention

When it happens

Trigger: Constructing AsyncDockerizedTerminal(container) and immediately calling execute() without await init(); init() raising in _ensure_workdir (error 48) and the caller still proceeding to execute().

Common situations: Skipping the context manager in quick scripts; swallowing an init() exception with a broad try/except and continuing; two coroutines sharing one terminal where one fails init first.

Related errors


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