MySQL ERROR 2006/2013: MySQL server has gone away – causes and fixes
ERROR 2006 (CR_SERVER_GONE_ERROR) and ERROR 2013 (CR_SERVER_LOST) produce the messages “MySQL server has gone away” and “Lost connection during query.” They often appear together, but they indicate different failures. ERROR 2006 means the server closed a connection the client believed was valid. ERROR 2013 means the connection dropped while a query was executing or results were transferring.
Treating them identically leads to incorrect fixes. Raising max_connections does not stop idle timeouts. Tuning timeouts does not fix an OOM kill. Before changing configuration, determine whether the MySQL process restarted. A stable process points to timeout or packet mismatches. A restarted process points to a crash or memory exhaustion.
What this means
ERROR 2006 (CR_SERVER_GONE_ERROR) occurs when the server terminates a connection. The client sends a query and finds the TCP socket already closed. Triggers include idle timeouts (wait_timeout or interactive_timeout), a packet exceeding max_allowed_packet, or a server crash. This error usually surfaces when a connection pool reuses a connection MySQL has already closed.
ERROR 2013 (CR_SERVER_LOST) occurs when the connection drops during active work. Triggers include a server crash mid-query, the server aborting a stalled client send via net_read_timeout, the server aborting a blocked result flush via net_write_timeout, or a client read timeout expiring during long execution.
First, check whether the MySQL process restarted. If it did, both errors are symptoms of a crash or OOM kill. If uptime is stable, the errors are configuration or workload mismatches. Check Uptime first.
flowchart TD
A[Client sees ERROR 2006 or 2013] --> B{Did Uptime reset?}
B -->|Yes| C[Server crashed or OOM killed]
B -->|No| D{Which error?}
D -->|ERROR 2006| E[Idle timeout or max_allowed_packet]
D -->|ERROR 2013| F[net_read_timeout, net_write_timeout, or client timeout]
E --> G[Check wait_timeout against pool lifetime]
F --> H[Check payload direction and duration]
C --> I[Review error log and memory pressure]Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
| Idle connection timeout | ERROR 2006 after a connection sits idle; spikes in Aborted_clients | SHOW GLOBAL VARIABLES LIKE 'wait_timeout'; compared to connection pool lifetime |
| max_allowed_packet exceeded | ERROR 2006 immediately after a large INSERT, UPDATE, or LOAD DATA | SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet'; |
| Server crash or OOM | Both ERROR 2006 and 2013 across many clients at the same time; Uptime reset | SHOW GLOBAL STATUS LIKE 'Uptime'; and the error log |
| Query network timeout | ERROR 2013 during long queries, bulk inserts, or large result sets | net_read_timeout, net_write_timeout, client read timeout, and the slow query log |
| Connection pool mismatch | ERROR 2006 when a pool returns a stale connection to the application | Pool max lifetime versus wait_timeout |
Quick checks
# Check server uptime to detect a recent restart
mysql -e "SHOW GLOBAL STATUS LIKE 'Uptime';"
# Check idle and interactive timeout values
mysql -e "SHOW GLOBAL VARIABLES WHERE Variable_name IN ('wait_timeout', 'interactive_timeout');"
# Check maximum allowed packet size
mysql -e "SHOW GLOBAL VARIABLES LIKE 'max_allowed_packet';"
# Check network read and write timeouts
mysql -e "SHOW GLOBAL VARIABLES WHERE Variable_name IN ('net_read_timeout', 'net_write_timeout');"
# Check aborted client and connection counters
mysql -e "SHOW GLOBAL STATUS WHERE Variable_name LIKE 'Aborted_%';"
# Review current connections and idle times
mysql -e "SELECT ID, USER, HOST, DB, COMMAND, TIME, STATE FROM information_schema.PROCESSLIST ORDER BY TIME DESC LIMIT 20;"
# Identify long-running active transactions
mysql -e "SELECT trx_mysql_thread_id, trx_started, TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS age_seconds, trx_query FROM information_schema.INNODB_TRX ORDER BY trx_started ASC;"
# Locate the error log file path
mysql -e "SHOW GLOBAL VARIABLES LIKE 'log_error';"
How to diagnose it
- Check
Uptime. If it is lower than the time since the connection was opened, the server restarted. Read the error log for OOM killer signatures, assertion failures, or InnoDB recovery messages. A restart explains simultaneous ERROR 2006 and 2013 across clients. - If uptime is stable, check
Aborted_clientsandAborted_connects. A sustained rise inAborted_clientscorrelates with timeouts or packet limits. A spike inAborted_connectspoints to handshake or network issues. - Compare
wait_timeoutto the connection pool max lifetime. If the pool holds connections longer thanwait_timeout, MySQL closes them and the pool serves stale sockets. - For ERROR 2013, distinguish direction. If the client was sending a large payload, compare send duration to
net_read_timeout. If the server was returning results, compare transfer time tonet_write_timeoutor check the client read timeout. Check the slow query log orinformation_schema.PROCESSLISTfor duration. - For errors during bulk operations, verify
max_allowed_packet. Payloads exceeding this limit cause an immediate disconnect. Check both server and client values. A common mismatch occurs when a dump created on a server with a larger default is restored to an instance with a smaller setting. - Check
information_schema.INNODB_TRXfor idle transactions. They do not directly cause ERROR 2006, but they indicate connection hygiene problems that correlate with misconfigured timeouts. - If errors affect only certain workers, verify that forked processes do not share MySQL connection file descriptors. Prefork application servers often inherit parent connections.
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
Uptime | A reset confirms the server restarted, explaining a wave of errors | Value lower than the time since the last known connection |
Aborted_clients | Rises when the server closes established connections abnormally | Sustained rate above the baseline |
Aborted_connects | Rises during handshake failures and network drops | Sudden spike or rate above 10 per minute |
Threads_connected / max_connections | Saturated connection slots prevent clean reconnections | Sustained ratio above 0.8 |
Threads_running | High active concurrency delays responses past timeout windows | Sustained value above 4 times CPU core count |
| Slow query rate | Queries exceeding long_query_time often also exceed client timeout windows | Rate increases more than 3 times baseline |
Fixes
Idle timeout mismatch
Align wait_timeout with your connection pool. Set wait_timeout slightly below the pool’s maximum connection lifetime. This lets the pool retire connections gracefully before MySQL closes them. If you run interactive monitoring tools alongside the application, remember that interactive_timeout applies to connections opened with the interactive client flag.
Tradeoff: Lowering the timeout increases reconnection overhead and can raise CPU usage from thread creation. Raising it accumulates idle connections that consume memory and file descriptors. High Threads_connected with low Threads_running indicates idle connection accumulation.
max_allowed_packet exceeded
Increase max_allowed_packet on the server to accommodate your largest payload, and ensure the client library is configured to match. For large restore operations, increase it temporarily to the upper limit. After the restore, return it to a conservative value.
Tradeoff: Very large packets increase per-connection memory usage and can raise OOM risk under high concurrency. Each connection buffer scales with this setting.
Query network timeout
If the client times out while sending data, increase net_read_timeout at the session level. If the server aborts while streaming results, increase net_write_timeout. If the client library gives up waiting for rows, increase the client read timeout. Prefer rewriting the query, adding pagination, or using a read replica for heavy reporting.
Tradeoff: Longer timeouts mask network instability and keep server resources tied up for extended periods. They also delay detection of genuinely stalled clients.
Server crash or OOM
If the OOM killer terminated mysqld, reduce memory pressure by lowering innodb_buffer_pool_size or max_connections. Increasing max_connections without increasing RAM trades connection refused errors for OOM kills. If the crash is query-related, capture the query from the error log and test it in a non-production environment.
Tradeoff: Memory changes require a restart. Do not increase swap to compensate, as this converts a fast failure into a slow stall.
Prevention
- Connection pool alignment. Set pool max lifetime lower than
wait_timeout. Revisit this after deployments or framework upgrades. Pools that discard connections after a fixed idle window are especially sensitive to this. - Packet size audits. Review application code for unbounded BLOB or JSON inserts. Set
max_allowed_packetexplicitly rather than relying on defaults that differ across versions. - Query design. Break large updates into smaller transactions. Paginate large SELECTs. Monitor the slow query log to catch queries approaching timeout limits.
- Baseline abnormal disconnects. Monitor
Aborted_clientsandAborted_connects. A gradual rise is often the first symptom of a timeout mismatch. Correlate these with application release timestamps. - Reserve admin connections. Ensure
max_connectionsleaves headroom for emergency access during a connection storm. MySQL reserves one connection for a user withSUPERorCONNECTION_ADMIN, but this only helps if you can reach the server.
How Netdata helps
- Correlate
Aborted_clientsandAborted_connectswithThreads_connectedandThreads_runningto distinguish idle timeouts from genuine overload. - Alert on
Uptimeresets to catch crash-induced error waves immediately. - Monitor slow query rate alongside query latency to detect queries approaching client timeouts before they disconnect.
- Track
Innodb_buffer_pool_wait_freeand checkpoint age to rule out server-side stalls that look like network timeouts.
Related guides
- How MySQL actually works in production: a mental model for operators: /guides/mysql/how-mysql-works-in-production/
- MySQL Aborted_connects and Aborted_clients climbing: diagnosis: /guides/mysql/mysql-aborted-connections/
- MySQL adaptive hash index latch contention: high CPU, low throughput: /guides/mysql/mysql-adaptive-hash-index-latch-contention/
- MySQL binary logs filling the disk: expiry, lagging replicas, and purge: /guides/mysql/mysql-binary-log-disk-full/
- MySQL InnoDB buffer pool hit ratio collapse: the cliff edge: /guides/mysql/mysql-buffer-pool-hit-ratio-collapse/
- MySQL slow after restart: buffer pool warm-up and the cold cache: /guides/mysql/mysql-buffer-pool-not-warming-up/
- MySQL innodb_buffer_pool_size tuning: 60-80% of RAM and when that breaks: /guides/mysql/mysql-buffer-pool-sizing/
- MySQL Innodb_buffer_pool_wait_free > 0: buffer pool memory pressure: /guides/mysql/mysql-buffer-pool-wait-free/
- MySQL InnoDB checkpoint age: the redo log capacity signal nobody watches: /guides/mysql/mysql-checkpoint-age-monitoring/
- MySQL connection exhaustion: detection, diagnosis, and prevention: /guides/mysql/mysql-connection-exhaustion/
- MySQL innodb_deadlock_detect=OFF: when deadlock detection becomes the bottleneck: /guides/mysql/mysql-deadlock-detect-off-high-concurrency/
- MySQL ERROR 1213: Deadlock found when trying to get lock; try restarting transaction: /guides/mysql/mysql-deadlock-found/







