phpseclib/phpseclib · error · ConnectionClosedException

Connection closed attempting to forward data to SSH agent

Error message

Connection closed attempting to forward data to SSH agent

What it means

forwardData() relays agent protocol frames received over an SSH channel to the local ssh-agent socket. If fwrite fails to write the complete buffered frame to the agent socket, ConnectionClosedException is thrown indicating the agent connection dropped mid-forwarding.

Solutions

  1. Confirm ssh-agent is still running and responsive (ssh-add -l from the same environment).
  2. Catch ConnectionClosedException around SSH operations that trigger forwarding and recreate the Agent to re-open the socket.
  3. Restart the SSH session/forwarding channel after the agent connection is re-established.
  4. Check for local firewalls/AV or ulimits killing long-lived unix sockets.
  5. Reduce idle time between forwarded requests to avoid stale sockets.

Example fix

// before
$data = $agent->forwardData($channelData); // throws if agent socket died
// after
try {
    $data = $agent->forwardData($channelData);
} catch (\phpseclib4\Exception\ConnectionClosedException $e) {
    $agent = new \phpseclib4\System\SSH\Agent(); // reconnect to agent
    $data = null; // drop this frame; client can retry
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    $reply = $agent->forwardData($data);
} catch (\phpseclib4\Exception\ConnectionClosedException $e) {
    $agent = new \phpseclib4\System\SSH\Agent(); // reopen agent socket
    // signal the forwarding channel to retry the request
}

Prevention

When it happens

Trigger: An SSH client on the remote side is using agent forwarding and sends a signing request; the local agent socket ($this->fsock) is closed or errors while forwardData writes the accumulated socket_buffer to it.

Common situations: ssh-agent exited or restarted during an active forwarded session; timeout killed the local unix socket connection; too many concurrent forwarded requests exhausting the agent.

Understand the failure class

Related errors


AI-assisted analysis of phpseclib/phpseclib@1da055d918 (2026-09-18). Data as JSON: /api/errors/d08ee4286065b012. Report an issue: GitHub.

Appendix: source

Thrown at phpseclib/System/SSH/Agent.php:271

     * Forward data to SSH Agent and return data reply
     */
    public function forwardData(string $data): ?string
    {
        if ($this->expected_bytes > 0) {
            $this->socket_buffer .= $data;
            $this->expected_bytes -= strlen($data);
        } else {
            $agent_data_bytes = current(unpack('N', $data));
            $current_data_bytes = strlen($data);
            $this->socket_buffer = $data;
            if ($current_data_bytes != $agent_data_bytes + 4) {
                $this->expected_bytes = ($agent_data_bytes + 4) - $current_data_bytes;
                return null;
            }
        }

        if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
            throw new ConnectionClosedException('Connection closed attempting to forward data to SSH agent');
        }

        $this->socket_buffer = '';
        $this->expected_bytes = 0;

        $agent_reply_bytes = current(unpack('N', $this->readBytes(4)));

        $agent_reply_data = $this->readBytes($agent_reply_bytes);
        $agent_reply_data = current(unpack('a*', $agent_reply_data));

        return pack('Na*', $agent_reply_bytes, $agent_reply_data);
    }
}

View on GitHub (pinned to 1da055d918)