google-gemini/gemini-cli · critical · FatalSandboxError

Proxy container command '${command} ${proxyContainerArgs.joi

Error message

Proxy container command '${command} ${proxyContainerArgs.join(' ')}' exited with code ${code}, signal ${signal}

What it means

Thrown inside the close handler of the proxy container process when that process exits (with a code and signal) before the sandbox session completes. The proxy container brokers network access for the sandbox; its premature death is fatal. Note: throwing inside an async event handler ('close') will not be catchable by the caller's try/catch and surfaces as an unhandled error.

Source

Thrown at packages/cli/src/utils/sandbox.ts:851

            stdio: 'ignore',
          });
        } catch {
          // ignore
        }
      };

      // commented out as it disrupts ink rendering
      // proxyProcess.stdout?.on('data', (data) => {
      //   console.info(data.toString());
      // });
      proxyProcess.stderr?.on('data', (data) => {
        debugLogger.debug(`[PROXY STDERR]: ${data.toString().trim()}`);
      });
      proxyProcess.on('close', (code, signal) => {
        if (sandboxProcess?.pid) {
          process.kill(-sandboxProcess.pid, 'SIGTERM');
        }
        throw new FatalSandboxError(
          `Proxy container command '${command} ${proxyContainerArgs.join(' ')}' exited with code ${code}, signal ${signal}`,
        );
      });
      debugLogger.log('waiting for proxy to start ...');
      await execAsync(
        `until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`,
      );
      // connect proxy container to sandbox network
      // (workaround for older versions of docker that don't support multiple --network args)
      await execAsync(
        `${command} network connect ${SANDBOX_NETWORK_NAME} ${SANDBOX_PROXY_NAME}`,
      );
    }

    // spawn child and let it inherit stdio
    process.stdin.pause();
    sandboxProcess = spawn(command, args, {
      stdio: 'inherit',

View on GitHub (pinned to 5024443c72)

Solutions

  1. Inspect proxy container logs: `docker logs <SANDBOX_PROXY_NAME>` (run right after the failure) for the root cause.
  2. Ensure port 8877 is free: `lsof -i :8877` and stop any conflicting process.
  3. Verify the proxy image exists and the Docker daemon has adequate memory/CPU.
  4. Re-run the sandbox command; transient daemon issues often clear on retry.
Defensive patterns

Strategy: try-catch

Validate before calling

const { execSync } = require('child_process');
// Pre-flight checks before starting the sandbox with a proxy.
execSync('lsof -i :8877', {stdio:'ignore'}); // throws if free — invert logic in your helper
try { execSync(`docker image inspect ${SANDBOX_PROXY_IMAGE}`, {stdio:'ignore'}); }
catch { execSync(`docker pull ${SANDBOX_PROXY_IMAGE}`, {stdio:'inherit'}); }

Try / catch

// Because the throw happens inside an event handler it cannot be caught by the caller.
// Instead, listen on the proxy process yourself or check liveness after start.
proxyProcess.on('close', (code, signal) => {
  log.warn(`proxy exited code=${code} signal=${signal}`);
  // graceful degradation / restart logic here
});

Prevention

When it happens

Trigger: The proxy container command (command + proxyContainerArgs, e.g. docker run for SANDBOX_PROXY_NAME on port 8877) exits — crash, OOM kill, daemon restart, or manual stop — triggering proxyProcess.on('close'). The handler also sends SIGTERM to the sandbox process group before throwing.

Common situations: Proxy image missing or fails to start. Port 8877 already in use by another process. Docker daemon restarted mid-session. Resource limits (memory/CPU) killed the proxy container. Network creation/connection step failed and the proxy was torn down.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/cdfa2e4dd18f13f0. Report an issue: GitHub.