Skip to main content
DevOpsintermediate

ERROR 2006: MySQL Server Has Gone Away

Fix ERROR 2006: MySQL server has gone away. Tell a packet-size failure from an idle timeout from a crashed server, and apply the right fix for each.

10 min readUpdated August 2026

ERROR 2006 (HY000): MySQL server has gone away means your client tried to use a connection the server had already closed:

ERROR 2006 (HY000): MySQL server has gone away

The related error you may see instead is:

ERROR 2013 (HY000): Lost connection to MySQL server during query

The distinction matters: 2006 means the client could not even send its request, while 2013 means the request went out and no complete answer came back. 2013 points more strongly at a crash or a break mid-query.

This message is a symptom with several unrelated causes. The fastest route to a fix is to work out which one you have before changing any setting.

Why This Happens — Narrow It Down First

Answer one question: does it fail instantly and reproducibly on the same statement, or unpredictably after a period of inactivity?

SymptomMost likely causeSection
Same statement fails every time, immediatelyStatement exceeds max_allowed_packetFix 1
First query after a quiet period fails; a retry workswait_timeout closed an idle connectionFix 2
Many connections fail at once, across applicationsServer restarted or was killedFix 3
Fails part-way through a long querynet_read_timeout / net_write_timeout, or a crashFix 4
One connection dies while others are fineThread was killedFix 5

Fix 1: Statement Larger Than max_allowed_packet

If a single statement — a bulk INSERT, a large BLOB, a long IN (...) list — exceeds max_allowed_packet, the server closes the connection instead of replying. This is the most common cause of a reproducible 2006.

SELECT @@global.max_allowed_packet, @@session.max_allowed_packet;

The MySQL 8 default is 64MB, but managed platforms and older versions often ship far lower values. The smaller of the client and server values wins, so raising it on one side alone does nothing.

Set it on the server in an option file so it survives restarts:

# /etc/mysql/mysql.conf.d/mysqld.cnf  (path varies by distribution)
[mysqld]
max_allowed_packet = 128M

You can also raise it at runtime without a restart, though it applies to new connections only:

SET GLOBAL max_allowed_packet = 134217728;   -- 128MB, resets on restart

Then set the matching client or driver value — --max-allowed-packet for the CLI, or the driver's equivalent option.

Size it to your largest legitimate statement plus headroom, not to the maximum. The setting exists to bound how much memory a single statement can force the server to allocate, so a very large value on a busy server is a memory-pressure risk. Where you control the code, the better fix is to send less: split bulk inserts into batches and store large objects outside the row.

Fix 2: Idle Connection Closed by wait_timeout

The server closes connections that have been idle for wait_timeout8 hours by default. Long-lived pooled connections, cron jobs, and worker processes that sit between statements all run into this.

SHOW GLOBAL VARIABLES LIKE '%timeout%';

Look at wait_timeout (non-interactive clients) and interactive_timeout (interactive ones such as the CLI).

The right fix is on the client. A connection pool should never hand out a connection it has not validated:

  • Validation query — the pool runs SELECT 1 before lending a connection, discarding dead ones.
  • Max lifetime — set the pool's maximum connection lifetime below the server's wait_timeout so the pool retires connections before the server closes them.
  • Idle eviction — close connections that have been idle beyond a threshold.

Raising wait_timeout instead means more idle connections held open against max_connections, which trades this error for a different one. Only raise it when you have a specific workload that genuinely needs long idle periods.

The mysql command-line client reconnects automatically, which is why this cause often looks invisible from the CLI and obvious from the application.

Advertisement

Fix 3: The Server Restarted or Was Killed

If many connections fail simultaneously across different applications, suspect the server rather than any one client.

SHOW GLOBAL STATUS LIKE 'Uptime';

If Uptime is smaller than the age of your connection, the server restarted underneath you. Confirm what happened:

# Did the kernel's OOM killer take mysqld?
dmesg -T | grep -i -E "oom|killed process"

# Was it a clean shutdown or a crash?
sudo systemctl status mysql

Then read the error log, which records shutdowns, signals, and startup — see where MySQL logs are stored for the path on your platform. An OOM kill usually means innodb_buffer_pool_size plus per-connection buffers times max_connections exceeds available RAM; a crash on a specific query means the query is the trigger and belongs in a bug report.

Fix 4: Timeouts During a Long Query

net_read_timeout and net_write_timeout govern how long the server waits on a network read or write while a statement is in flight. A slow client that cannot consume a large result set fast enough can trip these.

SHOW GLOBAL VARIABLES LIKE 'net_%timeout';

Before raising them, rule out a crash — a server that died mid-query produces the same symptom, and increasing a timeout will not fix that. Check Uptime first as in Fix 3. If the server is genuinely up and the client is genuinely slow, streaming the result set rather than buffering it whole is usually a better fix than a longer timeout.

Fix 5: The Thread Was Killed

A KILL statement, an administrative script, or a proxy enforcing its own limits will produce 2006 on exactly one connection while everything else is healthy. Check whether something is killing long-running threads on a schedule — many managed platforms and connection proxies do this by default, and their idle or query timeout is frequently shorter than MySQL's own.

Verify the Fix

Confirm the values actually in force, and that they agree on both sides:

SELECT @@global.max_allowed_packet AS server_packet,
       @@global.wait_timeout       AS wait_timeout,
       @@global.interactive_timeout AS interactive_timeout;
SHOW GLOBAL STATUS LIKE 'Uptime';
SHOW GLOBAL STATUS LIKE 'Aborted_clients';

Aborted_clients climbing steadily is the signature of connections being closed rather than closed cleanly by the application. Watch it over a few minutes rather than reading it once.

Then reproduce the original failure. For a packet-size problem, run the exact statement that failed. For an idle timeout, leave a pooled connection idle past the old threshold and use it again.

Read the Server's Side of the Story

The client only knows the connection vanished; the server knows why. Set verbose logging so aborted connections are recorded with a reason:

SET GLOBAL log_error_verbosity = 3;

Then look for Aborted connection lines naming the user, host, and cause. Distinguishing "got timeout reading communication packets" from "got an error reading communication packets" from a shutdown message tells you which of the fixes above applies, without guessing. See where MySQL logs are stored for where to find it.

Prevent It Coming Back

  • Validate pooled connections and keep the pool's max lifetime below the server's wait_timeout. This alone eliminates the most common recurring case.
  • Batch large writes instead of raising max_allowed_packet to cover a single enormous statement.
  • Keep max_allowed_packet consistent between server and client configuration, and set it in an option file so a restart does not silently revert it.
  • Alert on Aborted_clients so you see the trend before users report failures.
  • Size memory against max_connections so the server is not one traffic spike away from an OOM kill.
  • Handle reconnection in application code. Even a perfectly tuned server restarts for patching; a pool that retries once on a dead connection turns an outage into a blip.

Next Steps

Frequently Asked Questions

Find answers to common questions

The client tried to use a connection that the server had already closed, or the server closed it mid-statement. It is a symptom with several unrelated causes — an oversized packet, an idle timeout, a killed thread, or a crashed server — so the fix depends entirely on which one applies.

2006 (CR_SERVER_GONE_ERROR, 'MySQL server has gone away') means the client could not send its request because the connection was already gone. 2013 (CR_SERVER_LOST, 'Lost connection to MySQL server during query') means the request went out but no complete answer came back. 2013 more often points at a crash or a network break mid-query.

Yes, and it is the most common cause for a query that fails instantly and reproducibly. If a single statement or a BLOB exceeds max_allowed_packet, the server drops the connection rather than replying. The default in MySQL 8 is 64MB, but many managed platforms and older versions set it far lower.

The server closes idle connections after wait_timeout, which defaults to 8 hours. Long-lived pooled connections and cron jobs that sit between statements hit this. The fix is connection validation in the pool, not simply raising wait_timeout.

Run SHOW GLOBAL STATUS LIKE 'Uptime' — if the value is smaller than the age of your connection, the server restarted. Then check the error log for a shutdown or a signal, and run dmesg -T | grep -i oom to see whether the kernel's out-of-memory killer terminated mysqld.

Usually not, despite how it reads. A firewall or load balancer idle timeout can cut a connection, but it is worth ruling out packet size, wait_timeout, and a server restart first — those account for most cases and are easier to confirm.

It must be large enough on both the server and the client, because the smaller of the two wins. Set it in the server's option file so it survives restarts, and configure the matching client or driver setting. Size it to your largest legitimate statement plus headroom rather than to the maximum.

The mysql command-line client reconnects automatically, which hides the problem. Pools hand out connections that have been sitting idle since the server closed them. Enable the pool's validation query or max-lifetime setting so dead connections are discarded before use.

It can, through net_read_timeout and net_write_timeout, which govern how long the server waits on a network read or write during a statement. It can also be a symptom of the server being killed while the query ran, so check uptime and the error log before increasing timeouts.

The MySQL error log. Set log_error_verbosity to 3 to record aborted connections, then look for 'Aborted connection' lines naming the user, host, and reason. A shutdown message or a signal means the server went down rather than closing one connection.