{"record":{"id":"5b7ddb7154fe77f9","repo":"Hmbown/CodeWhale","slug":"docker-exec-container-timed-out","errorCode":null,"errorMessage":"docker exec ${container}: timed out","messagePattern":"docker exec (.+?): timed out","errorType":"exception","errorClass":"ExecError","httpStatus":null,"severity":"error","filePath":"crates/tui/plugins/computer-use/src/transport.mjs","lineNumber":258,"sourceCode":" * the container entrypoint recorded before serving requests.\n */\nexport function dockerExec(computer, binding) {\n  const container = safeRemotePath(computer.container);\n  const remoteAgent = \"/app/docker/agent-exec.sh\";\n  const ex = {\n    kind: \"docker\",\n    container,\n    remoteAgent,\n    run(cmd, args = [], opts = {}) {\n      // Local side commands (docker itself) run directly.\n      return run(cmd, args, opts);\n    },\n    async remote(request, opts = {}) {\n      const r = await run(\"docker\", [\"exec\", container, \"/bin/sh\", remoteAgent, b64({ args: request.args ?? {}, tool: request.tool, nonce: crypto.randomBytes(6).toString(\"hex\") })], {\n        timeoutMs: opts.timeoutMs ?? 25_000,\n      });\n      if (r.aborted) throw Object.assign(new ExecError(\"computer request cancelled\", r), { code: \"cancelled\" });\n      if (r.timedOut) throw new ExecError(`docker exec ${container}: timed out`, r);\n      if (r.code !== 0) throw new ExecError(`docker exec ${container} exited ${r.code}: ${r.stderr.trim().slice(0, 400)}`, r);\n      const line = r.stdout.trim().split(\"\\n\").filter((l) => l.startsWith(\"{\")).pop();\n      const reply = line ? JSON.parse(line) : null;\n      if (!reply) throw new ExecError(`docker exec ${container}: agent returned no JSON receipt`, r);\n      return reply;\n    },\n  };\n  attachPersistentChannel(ex, binding, [\"docker\", \"exec\", \"-i\", container, \"/bin/sh\", remoteAgent, \"--serve\"]);\n  return ex;\n}\n\n/** Push the self-contained remote agent + src tree to an ssh computer. */\nexport async function installRemoteAgent(computer) {\n  const ex = sshExec(computer);\n  const srcDir = path.join(PLUGIN_ROOT, \"src\");\n  const rels = [\"agent.mjs\"];\n  for (const dir of [\"\", \"backends\"]) {\n    const full = path.join(srcDir, dir);","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/plugins/computer-use/src/transport.mjs#L240-L276","documentation":"The Docker transport runs the remote agent via `docker exec` with a timeout (default 25s). When the run exceeds that limit it throws this ExecError signalling the docker exec timed out. It exists so callers can distinguish slow-hanging container commands from hard failures.","triggerScenarios":"executor.remote() on a docker transport where the `docker exec` invocation does not complete within opts.timeoutMs (default 25_000 ms): container paused, overloaded host, agent blocking on I/O, or docker daemon unresponsive.","commonSituations":"Container under heavy load or OOM-swapping; docker daemon stalled; agent waiting on a GUI/screenshot operation that never returns; host disk contention; running on a very slow remote machine.","solutions":["Raise the timeout: pass { timeoutMs: 60000 } (or higher) in opts to remote()","Check container health: docker ps, docker logs <container>, docker stats","Retry the request — a transient stall often resolves","Ensure the container is running and not paused: docker unpause <container>","Investigate the agent-side operation (e.g. screenshot) that may block indefinitely"],"exampleFix":"// before\nawait ex.remote({ tool: \"screenshot\" }); // default 25s too short\n// after\nawait ex.remote({ tool: \"screenshot\" }, { timeoutMs: 120_000 });","handlingStrategy":"retry","validationCode":"// check container is running and responsive before the call\nconst st = await run(\"docker\", [\"inspect\", \"-f\", \"{{.State.Running}}\", container]);\nif (st.code !== 0 || st.stdout.trim() !== \"true\") throw new Error(`container ${container} not running`);","typeGuard":"function isDockerTimeout(e) { return e instanceof ExecError && e.message.includes(\": timed out\"); }","tryCatchPattern":"try {\n  return await ex.remote(request, opts);\n} catch (e) {\n  if (e.message.includes(\"timed out\") && attempts < 3) return retryWithBackoff(attempts + 1, { ...opts, timeoutMs: (opts.timeoutMs ?? 25000) * 2 });\n  throw e;\n}","preventionTips":["Pass an explicit timeoutMs suited to the tool (screenshots need more than 25s)","Monitor container health (docker stats) for slow hosts","Avoid calling remote tools while the container is paused or overloaded"],"tags":["docker","timeout","remote-execution"],"backgroundTag":"request-timeout","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}