How to fix client_loop: send disconnect: Broken pipe in SSH

SSHBEGINNERMEDIUMUpdated Oct 3, 2026· 423 views

The "client_loop: send disconnect: Broken pipe" error occurs when an idle SSH connection is terminated by the server, firewall, or NAT device due to inactivity timeout. It's common in remote work and cloud environments where keepalive settings aren't configured.

Quick fix

Fixes client_loop: send disconnect: Broken pipe

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
  1. Enable keepalive on your SSH client (quickest fix)
  2. Enable TCP keepalive as additional layer
  3. Configure server-side keepalive (if you have server access)
  4. Adjust keepalive interval for restrictive networks
ssh — error
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
client_loop: send disconnect: Broken pipe

What this error means

This error appears when your SSH session becomes inactive for too long and the server (or an intermediate firewall/NAT/router) closes the connection. SSH is a stateful protocol—if no data flows for several minutes, network infrastructure assumes the connection is dead and terminates it. When your client tries to send the next command, it discovers the broken pipe and displays this error. This is purely a connectivity issue—your credentials and permissions are fine; the connection itself was dropped.

Typical symptoms

  • SSH session disconnects suddenly after sitting idle for a few minutes
  • Error appears after running a long-running command or during an unattended session
  • Manual SSH commands work, but leaving a terminal open without activity causes disconnect
  • Happens consistently after the same idle period (usually 5-15 minutes)
  • Running commands immediately after connecting works fine
  • Works on some networks (office WiFi) but fails on others (VPN, corporate firewall)
  • More frequent when using SSH tunnels or bastion hosts

Common causes

  1. SSH client not sending keepalive packets to prevent server from timing out the connection
  2. Server-side keepalive configuration (ClientAliveInterval) not enabled or set too high
  3. Firewall or NAT device between client and server dropping idle TCP connections
  4. Router or ISP closing dormant connections after 5-15 minutes of inactivity
  5. Cloud environment aggressive timeout settings to conserve resources
  6. Network middleware (proxy, load balancer) enforcing strict idle timeouts
  7. Terminal session left unattended without any activity for extended period

How to fix "client_loop: send disconnect: Broken pipe"

1Enable keepalive on your SSH client (quickest fix)

Configure your SSH client to send keepalive packets every 60 seconds. Add to ~/.ssh/config:

bash
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

This tells your SSH client to send a null packet every 60 seconds to keep the connection alive. ServerAliveCountMax 3 means it will retry 3 times before giving up (total: 180 seconds of no response).

Alternatively, use on command-line for one-off connections:

bash
ssh -o ServerAliveInterval=60 user@hostname

This is the most reliable client-side fix and works immediately without server changes.

2Enable TCP keepalive as additional layer

Add TCPKeepAlive to your SSH config to send TCP-level keepalives:

bash
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    TCPKeepAlive yes

TCPKeepAlive uses lower-level TCP keepalive probes. Combined with ServerAliveInterval, this provides redundant keepalive mechanisms and is especially useful if SSH-level keepalives alone aren't working.

3Configure server-side keepalive (if you have server access)

If you have access to the SSH server, configure server-side keepalive settings. Edit /etc/ssh/sshd_config:

bash
sudo nano /etc/ssh/sshd_config

Add or update:

bash
ClientAliveInterval 300
ClientAliveCountMax 3

This tells the server to send a keepalive packet every 300 seconds (5 minutes) if no activity from client, retrying 3 times.

After editing, restart SSH service:

bash
sudo systemctl restart sshd

ServerAliveInterval on the client is usually enough, but server-side config helps when many clients connect with stale settings.

4Adjust keepalive interval for restrictive networks

If you experience disconnects on a specific network (VPN, corporate firewall), reduce the ServerAliveInterval to send packets more frequently:

bash
Host restrictive-network
    ServerAliveInterval 30
    ServerAliveCountMax 5
    TCPKeepAlive yes

This sends keepalive packets every 30 seconds (instead of 60), which stays ahead of aggressive firewall timeouts (typically 5-15 minutes).

For particularly troublesome networks:

bash
Host very-restrictive
    ServerAliveInterval 20
    ServerAliveCountMax 3
    TCPKeepAlive yes
    ExitOnForwardFailure yes

Lower intervals use slightly more bandwidth but guarantee the connection never sits idle.

5Use mosh as alternative for unstable connections

If SSH keepalive settings don't solve the problem (especially for mobile/WiFi), consider using mosh (mobile shell):

bash
sudo apt-get install mosh  # Debian/Ubuntu
sudo yum install mosh      # RHEL/CentOS
brew install mosh          # macOS

Then connect:

bash
mosh user@hostname

Mosh is designed for mobile/unreliable connections:
- Tolerates network changes (WiFi to cellular)
- Automatically reconnects on temporary network loss
- Lower bandwidth usage
- Supports disconnecting/reconnecting without losing session

Mosh runs on top of SSH, so your server still needs SSH; it's a better shell for roaming connections.

6Check firewall/proxy settings if keepalive doesn't work

If keepalive settings don't resolve the issue, your network may have aggressive filtering:

bash
# Test if packets are actually being sent
ssh -vv user@hostname

Look for lines like "Sending SSH2_MSG_IGNORE" or "Packet type..." which confirm keepalive is active.

If still disconnecting:
- Check if you're behind a corporate proxy (ask your network admin)
- Test on a different network (home WiFi, cellular hotspot, VPN)
- Contact your ISP if it's a home internet issue
- For cloud VMs, check the security group/firewall rules allow outbound SSH

If behind a proxy:

bash
Host proxy-host
    ProxyCommand ssh bastion-host 'nc %h %p'
    ServerAliveInterval 60

Ensure keepalive settings are on both the client and bastion connections.

Advanced notes

Advanced Troubleshooting:

Ubuntu 24.04+ Behavior Change: Ubuntu 24.04 and later changed SSH default keepalive behavior. If you recently upgraded and now see broken pipe errors, add explicit TCPKeepAlive settings to restore previous behavior.

EC2 and Cloud VMs: Amazon AWS and other cloud providers often use aggressive NAT timeouts (5-15 minutes). Always set ServerAliveInterval to 60 or lower on connections to cloud instances.

SSH Tunnels and Port Forwarding: Tunnels with -L or -R flags are especially susceptible to idle timeouts. Apply keepalive settings twice: once for the tunnel itself, once in ~/.ssh/config for the host.

Bastion/Jump Host Connections: When using ssh -J bastion-host target-host, timeouts can occur on either leg. Enable keepalive on both:

bash
Host target-host
    ProxyJump bastion-host
    ServerAliveInterval 60
    ServerAliveCountMax 3

Host bastion-host
    ServerAliveInterval 60
    ServerAliveCountMax 3

VPN and Proxy Environments: Corporate VPNs and proxies have their own timeout settings (often very aggressive). If ServerAliveInterval 60 fails, reduce to ServerAliveInterval 30. Contact your network team for the VPN's idle timeout value.

Debugging: Run ssh with verbose flags to confirm keepalives are active:

bash
ssh -vv user@host  # Shows "Sending SSH2_MSG_IGNORE" packets

Mosh Alternative: For truly unreliable networks (mobile, WiFi roaming), mosh is superior. It tolerates network changes SSH cannot handle. However, it requires mosh to be installed on both client and server.

Frequently asked questions

What does "client_loop: send disconnect: Broken pipe" mean?
This error appears when your SSH session becomes inactive for too long and the server (or an intermediate firewall/NAT/router) closes the connection. SSH is a stateful protocol—if no data flows for several minutes, network infrastructure assumes the connection is dead and terminates it. When your client tries to send the next command, it discovers the broken pipe and displays this error.
How do I fix "client_loop: send disconnect: Broken pipe"?
The "client_loop: send disconnect: Broken pipe" error occurs when an idle SSH connection is terminated by the server, firewall, or NAT device due to inactivity timeout. It's common in remote work and cloud environments where keepalive settings aren't configured.
What causes "client_loop: send disconnect: Broken pipe"?
SSH client not sending keepalive packets to prevent server from timing out the connection Server-side keepalive configuration (ClientAliveInterval) not enabled or set too high Firewall or NAT device between client and server dropping idle TCP connections
Is the "client_loop: send disconnect: Broken pipe" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading