{"record":{"id":"e0c5d19253c55f3f","repo":"FoundationAgents/OpenManus","slug":"timed-out-bash-has-not-returned-in-self-timeout","errorCode":null,"errorMessage":"timed out: bash has not returned in {self._timeout} seconds and must be restarted","messagePattern":"timed out: bash has not returned in (.+?) seconds and must be restarted","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"app/tool/bash.py","lineNumber":65,"sourceCode":"    def stop(self):\n        \"\"\"Terminate the bash shell.\"\"\"\n        if not self._started:\n            raise ToolError(\"Session has not started.\")\n        if self._process.returncode is not None:\n            return\n        self._process.terminate()\n\n    async def run(self, command: str):\n        \"\"\"Execute a command in the bash shell.\"\"\"\n        if not self._started:\n            raise ToolError(\"Session has not started.\")\n        if self._process.returncode is not None:\n            return CLIResult(\n                system=\"tool must be restarted\",\n                error=f\"bash has exited with returncode {self._process.returncode}\",\n            )\n        if self._timed_out:\n            raise ToolError(\n                f\"timed out: bash has not returned in {self._timeout} seconds and must be restarted\",\n            )\n\n        # we know these are not None because we created the process with PIPEs\n        assert self._process.stdin\n        assert self._process.stdout\n        assert self._process.stderr\n\n        # send command to the process\n        self._process.stdin.write(\n            command.encode() + f\"; echo '{self._sentinel}'\\n\".encode()\n        )\n        await self._process.stdin.drain()\n\n        # read output from the process, until the sentinel is found\n        try:\n            async with asyncio.timeout(self._timeout):\n                while True:","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/FoundationAgents/OpenManus/blob/52a13f2a57d8c7f6737eefb02ccf569594d44273/app/tool/bash.py#L47-L83","documentation":"run() refuses new commands once _timed_out is set: a previous command exceeded _timeout, and the session no longer trusts its output stream (the sentinel line from the hung command may still arrive later and corrupt the next read). The message says explicitly the session 'must be restarted' — recovery is a restart, not a retry.","triggerScenarios":"Command A times out (error 53 fires, _timed_out = True); command B is then sent to the same session and is rejected here before anything is written to the shell.","commonSituations":"Agent loops that keep issuing commands after catching a ToolError timeout; timeout handlers that log but do not recycle the session.","solutions":["After a timeout ToolError, restart the session before the next command: create a new _BashSession, or with the outer Bash tool call execute(\"restart\").","Catch this exact ToolError separately from timeouts: 'timed out' in str(e) → recycle session, then re-issue or skip the command.","Prevent the original timeout (see error 53): larger _timeout, or avoid commands that never print the sentinel."],"exampleFix":"# before\ntry:\n    out = await bash.execute(cmd)\nexcept ToolError:\n    out = await bash.execute(next_cmd)  # ToolError: must be restarted\n\n# after\ntry:\n    out = await bash.execute(cmd)\nexcept ToolError as e:\n    if \"timed out\" in str(e):\n        out = await bash.execute(\"restart\")   # fresh session\n    out = await bash.execute(next_cmd)","handlingStrategy":"fallback","validationCode":"if session._timed_out:\n    session = _BashSession()\n    await session.start()  # or: await bash.execute('restart')","typeGuard":"def needs_restart(s: _BashSession) -> bool:\n    return bool(s._timed_out)","tryCatchPattern":"try:\n    out = await bash.execute(cmd)\nexcept ToolError as e:\n    if 'must be restarted' in str(e):\n        await bash.execute('restart')       # fallback: fresh session\n        out = await bash.execute(cmd)\n    else:\n        raise","preventionTips":["After any timeout, restart the session before the next command.","Distinguish 'must be restarted' from other ToolErrors in handlers.","Fix the root cause (error 53) so the flag never gets set."],"tags":["bash","timeout","session-restart","tool-error"],"backgroundTag":null,"analyzedSha":"52a13f2a57d8c7f6737eefb02ccf569594d44273","analyzedAt":"2026-08-15T02:33:49.993Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}