Cause #1: You hit the max_connections ceiling
The most common reason for ERROR 1040 is that your MySQL server has a hard cap on simultaneous connections, and you've reached it. The default value is 151 on MySQL 5.7 and 8.0. If you're running a busy application or multiple services pointing at the same database, that number gets eaten fast.
The quick fix: raise the limit temporarily, then make it permanent.
- Log into MySQL as root or a user with SUPER privileges. If you can't log in because you're already over the limit, try the debug socket trick first (see below).
- Check the current limit and how many connections are active:
SHOW VARIABLES LIKE 'max_connections';
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Max_used_connections';
Max_used_connections tells you the peak since the server started. If that's close to max_connections, you've been hitting the wall.
Now raise the limit on the fly (doesn't survive a restart):
SET GLOBAL max_connections = 500;
After that, try connecting again. You should get in. To make it permanent, edit your MySQL config file. On Ubuntu, that's usually /etc/mysql/mysql.conf.d/mysqld.cnf. On CentOS, it's /etc/my.cnf. Look under the [mysqld] section and add:
[mysqld]
max_connections = 500
Save the file and restart MySQL:
sudo systemctl restart mysql
After restart, run SHOW VARIABLES LIKE 'max_connections'; again — you should see 500.
When you can't even log in: If you're completely locked out, MySQL has a special debug socket that lets you in without checking the connection count. On most systems, you can restart MySQL with --skip-networking and then log in via the local socket. Or, if you're using systemd, you can start a second instance. But the simplest approach is to restart MySQL with a higher limit using a command line override:
sudo mysqld_safe --max_connections=1000 &
That should get you in, then you can permanently edit the config.
Raising max_connections is a band-aid, though. If you're constantly hitting the limit, you need to look at why. That's the next two causes.
Cause #2: Application connection leaks or excessive threads
Sometimes the limit is fine, but your application opens connections and never closes them. This usually shows up as Threads_connected climbing steadily over time, even when user traffic is flat. I've seen this from misconfigured connection pools in Java apps and from PHP scripts that forget to close the connection after the page renders.
How to check:
- Run this query to see which users and hosts are hogging connections:
SELECT user, host, db, command, time, state FROM information_schema.processlist;
Look for command of Sleep with high time values. Those are idle connections that should have been closed.
Real-world trigger: A WordPress plugin that uses mysql_pconnect (persistent connections) can leave dozens of sleeping connections around. Each Apache worker keeps its own connection open, and if the worker hangs around, so does the connection.
Fix the app, not just the server:
- In PHP, make sure you're not using persistent connections unless you absolutely need them. Set
mysqli.pconnect = 0inphp.ini. - In Java, check your connection pool (HikariCP, Tomcat JDBC) settings.
maximumPoolSizeshould be less than MySQL'smax_connections, andidleTimeoutshould be short, like 10 minutes. - In Python (SQLAlchemy), set
pool_sizeandmax_overflowcarefully, and usepool_recycleto avoid stale connections.
You can also reduce the time MySQL waits before closing idle connections:
SET GLOBAL wait_timeout = 60;
SET GLOBAL interactive_timeout = 60;
That kills idle connections after 60 seconds instead of the default 8 hours. But be careful — if your app genuinely needs long-lived connections, this can cause errors. Test it first.
If you're not sure which app is leaking, temporarily stop each app one at a time and watch Threads_connected drop. That tells you the culprit.
Cause #3: Too many connections from a single user or thread cache issue
Sometimes the problem isn't the total limit, but that one user is consuming all the connections. For example, a misconfigured monitoring tool that connects as root and opens 200 connections. Or you have a replication slave that's failing, and it keeps trying to reconnect, eating up connections.
Find the hog:
SELECT user, host, COUNT(*) AS cnt FROM information_schema.processlist GROUP BY user, host ORDER BY cnt DESC;
If one user has way more than their fair share, you can restrict them. First, create a dedicated user for that app if you haven't already. Then limit their max connections:
CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'strong_password';
GRANT ALL PRIVILEGES ON mydb.* TO 'myapp'@'localhost' WITH MAX_USER_CONNECTIONS 20;
After that, the app can only open 20 connections at a time. Adjust the number based on what the app needs — 20 is a starting point for a small web app.
Also check the thread_cache_size variable. It controls how many threads MySQL keeps cached for reuse. If it's set to 0, MySQL creates a new thread for every connection, which is slower and can cause connection storms under load. Set it to something like 16 or 32:
SET GLOBAL thread_cache_size = 32;
Add that to your config file too. It won't directly fix ERROR 1040, but it reduces the chance of hitting the limit under bursty load.
Real-world trigger: A cron job that runs every minute and connects as root without closing its connection — I've seen that cause 400 stuck connections from the same host. The fix was to fix the script and limit root connections.
Quick-reference summary table
| Symptom | Cause | Fix |
|---|---|---|
| Error appears during peak traffic | max_connections too low | Increase max_connections in config, restart MySQL |
| Threads_connected rises over time | Application leak or persistent connections | Fix connection pool settings, close connections in code |
| One user/host uses most connections | Monitoring script or cron hog | Set MAX_USER_CONNECTIONS for that user, fix the script |
Start with raising max_connections to get back online fast. Then dig into the process list to find the real cause. You'll often find a bad app or a forgotten script. That's the actual fix.