FoundationAgents/OpenManus · error · RuntimeError
Failed to get socket connection
Error message
Failed to get socket connection
What it means
After docker-py's exec_start(socket=True, tty=True, stream=True, demux=True), the code reaches into the private attribute socket_data._sock to grab the raw socket. If the returned object does not expose _sock (its shape differs across docker SDK versions and tty/demux combinations), terminal initialization fails with this RuntimeError. It is an implementation-detail dependency: docker-py does not guarantee _sock on every return type.
Source
Thrown at app/sandbox/core/terminal.py:71
stdin=True,
tty=True,
stdout=True,
stderr=True,
privileged=True,
user="root",
environment={**env_vars, "TERM": "dumb", "PS1": "$ ", "PROMPT_COMMAND": ""},
)
self.exec_id = exec_data["Id"]
socket_data = self.api.exec_start(
self.exec_id, socket=True, tty=True, stream=True, demux=True
)
if hasattr(socket_data, "_sock"):
self.socket = socket_data._sock
self.socket.setblocking(False)
else:
raise RuntimeError("Failed to get socket connection")
await self._read_until_prompt()
async def close(self) -> None:
"""Cleans up session resources.
1. Sends exit command
2. Closes socket connection
3. Checks and cleans up exec instance
"""
try:
if self.socket:
# Send exit command to close bash session
try:
self.socket.sendall(b"exit\n")
# Allow time for command execution
await asyncio.sleep(0.1)
except:View on GitHub (pinned to 52a13f2a57)
Solutions
- Pin the docker SDK version this code was developed against (check requirements/lockfile) — _sock access is version-sensitive.
- Drop demux=True when tty=True is used; the demux flag alters the returned structure and is redundant with a TTY (stdout/stderr are merged on a tty anyway).
- Handle more return shapes: check for _sock, then .sock, then treat the object itself as a socket (hasattr sendall/setblocking).
- Print type(socket_data) in a debug run to see exactly what your docker version returns before patching.
Example fix
# before
socket_data = self.api.exec_start(self.exec_id, socket=True, tty=True, stream=True, demux=True)
if hasattr(socket_data, "_sock"):
self.socket = socket_data._sock
else:
raise RuntimeError("Failed to get socket connection")
# after
socket_data = self.api.exec_start(self.exec_id, socket=True, tty=True, stream=True)
if hasattr(socket_data, "_sock"):
self.socket = socket_data._sock
elif hasattr(socket_data, "sendall"):
self.socket = socket_data
else:
raise RuntimeError(f"Unexpected exec_start return type: {type(socket_data)!r}")
self.socket.setblocking(False) Defensive patterns
Strategy: type-guard
Validate before calling
import docker, pkg_resources
major_minor = tuple(int(x) for x in docker.__version__.split('.')[:2])
assert major_minor == (7, 1), f'untested docker SDK {docker.__version__} for raw socket access' Type guard
def as_raw_socket(obj):
"""Extract a socket-like object from docker exec_start output."""
for attr in ('_sock', 'sock', '_sock_obj'):
s = getattr(obj, attr, None)
if s is not None and hasattr(s, 'sendall') and hasattr(s, 'setblocking'):
return s
if hasattr(obj, 'sendall'):
return obj
return None Try / catch
try:
await session.create(workdir, env)
except RuntimeError as e:
if 'Failed to get socket connection' in str(e):
raise RuntimeError(
'docker SDK returned an unexpected exec_start shape; pin docker==7.1.0 '
'or drop demux=True'
) from e
raise Prevention
- Pin the docker package version in requirements/lockfile.
- Avoid combining demux=True with tty=True.
- Never rely on private attributes (_sock) without a fallback path.
When it happens
Trigger: Calling DockerSession.__init__/create with a docker SDK version where exec_start returns a SocketIORunner, a wrapped socket, or a tuple (because demux=True changes the return shape) that lacks the _sock attribute. Mixing demux=True with tty=True is a known combination that changes the object shape.
Common situations: Upgrading or downgrading the 'docker' package in the environment; using a docker-py fork (docker-pydx) with a different socket plumbing layer; running against a docker daemon version whose API version renegotiation changes the returned object.
Related errors
- Failed to create sandbox: {e}
- Session not initialized
- Command execution timed out after {timeout} seconds
- Failed to execute command: {e}
- Terminal not initialized
AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15).
Data as JSON: /api/errors/2cb91a86aca05165.
Report an issue: GitHub.