Laravel SQLSTATE HY000 2002 Connection Refused: Solved
Fix the 'laravel sqlstate hy000 2002 connection refused' error reliably. Learn what causes it, step-by-step solutions, and best practice tips.
If you've worked with Laravel and MySQL (or MariaDB), you’ve probably come across the dreaded 'laravel sqlstate hy000 2002 connection refused' error. I’ve hit this issue multiple times, from local dev machines to production servers. In this detailed guide, I’ll break down what causes this connection error, show step-by-step troubleshooting, and share prevention tips. Expect hands-on code, actionable troubleshooting, and clear explanations throughout. [Official Laravel DB docs](https://laravel.com/docs/database)
What Does SQLSTATE HY000 2002 Connection Refused Mean?
When your Laravel app tries to connect to the database and gets a SQLSTATE[HY000] [2002] Connection refused error, it means Laravel failed to reach the MySQL (or MariaDB) server. This is usually a network, system configuration, or service-level issue—it's not about mismatched credentials, but more often about not reaching the database service at all.
- The MySQL/MariaDB service isn’t running or reachable
- The host and port might be wrong in Laravel’s config
- .env file changes haven't been applied or are cached
- Database socket or TCP port isn’t open or mapped
- Firewall, Docker, or SELinux/AppArmor misrouting
Prerequisites: What You Need to Check First
Make sure you have:
- Access to your server (local or remote) shell - Familiarity with editing your Laravel .env file - Permissions to restart MySQL/MariaDB or any service containers if needed - Laravel 8+ and PHP 7.4+ strongly recommended (older versions behave similarly, but some config nuances differ)
Step 1: Confirm Your MySQL/MariaDB Service Is Running
The most common cause is that MySQL or MariaDB is not running—all further troubleshooting is pointless otherwise. Even experienced devs (me included!) sometimes forget to start the service after a reboot.
sudo systemctl status mysql.service
# On older systems:
sudo service mysql status
# On MariaDB:
sudo systemctl status mariadb
# For Docker Compose:
docker compose ps | grep db
# Or general:
docker ps | grep mysqlStep 2: Verify Your .env Database Connection Settings
Laravel gets its DB connection details from the .env file. Make sure these values match your MySQL/MariaDB server setup. Typos or wrong host/port are classic culprits.
- DB_CONNECTION=mysql
- DB_HOST=127.0.0.1 # or 'localhost', see below
- DB_PORT=3306 # standard MySQL/MariaDB port
- DB_DATABASE=your_database
- DB_USERNAME=your_db_user
- DB_PASSWORD=your_db_pass
DB_CONNECTION=mysql
DB_HOST=127.0.0.1 # or your Docker service name, or a remote IP
DB_PORT=3306
DB_DATABASE=my_laravel_app
DB_USERNAME=laraveluser
DB_PASSWORD=secretpassStep 3: 127.0.0.1 vs. localhost: What’s the Difference?
Setting DB_HOST=localhost versus DB_HOST=127.0.0.1 can make a big difference. On many systems, and with PHP's default settings, 'localhost' makes the client use a Unix socket instead of TCP/IP, while '127.0.0.1' forces a TCP connection. If MySQL isn't set up to use sockets or your PHP config is missing the configured socket path, you’ll hit HY000 2002 connection refused.
- Try DB_HOST=127.0.0.1 first, especially within Docker or containers
- Use DB_HOST=localhost only if you know sockets are set up (check phpinfo() output for default socket path)
Step 4: Clearing Laravel Config Cache
When you update the .env, Laravel might still use cached config values. Always clear the config cache after changes.
php artisan config:clear
php artisan config:cacheStep 5: Check MySQL/MariaDB Is Using The Right Network Interface
If the error persists, confirm MySQL/MariaDB is listening for connections on the expected port and interface. On some installs, MySQL is bound only to 127.0.0.1 (loopback), not 0.0.0.0 (all interfaces), or vice versa. (For remote access, it must listen on more than localhost.)
# See which address and port MySQL is using
sudo ss -tlnp | grep mysql
# Alternative (if ss not available):
sudo netstat -lnptu | grep mysql
# Or
sudo lsof -i -n -P | grep mysqldStep 6: Firewall, SELinux, and Docker Networking Issues
Containers, VMs, and security layers often add more restrictions. On Docker, your DB_HOST might need to be your docker-compose service name (e.g., db) and not localhost. Host firewalls or SELinux/AppArmor may also block the port.
- Ensure MySQL/MariaDB port 3306 is exposed and mapped on the correct interface
- Use DB_HOST=db (your docker-compose service name) in Laravel when using Docker Compose
- TEMPORARILY disable the firewall/SELinux only to isolate the issue—re-enable and set correct rules after testing
Step 7: Testing The Connection from the PHP Container/Shell
Try connecting to MySQL/MariaDB from your running PHP or web container/shell, using the same credentials as in your .env file. This isolates whether it’s a Laravel code issue or a fundamental networking/configuration problem.
# In the host shell:
mysql -h 127.0.0.1 -u laraveluser -p
# Inside Docker app container (update container name if needed):
docker exec -it [your_app_container] bash
mysql -h db -u laraveluser -pStep 8: Checking Laravel Log Files for Details
Laravel's storage/logs/laravel.log will show the full stack trace and deeper config issues. Search for 'HY000' or 'Connection refused' to confirm the error details—or spot a different underlying problem.
Common Pitfalls and Their Fixes
Here’s a shortlist of frequent production issues:
- Forgot to restart MySQL/MariaDB after an update or config tweak - Mistyped DB_HOST or DB_PORT, especially in multi-container setups - Database running and bound to 127.0.0.1, but app tries to connect from another network host - .env changes not picked up due to config cache - Firewalls silently blocking port 3306
- Always cross-check actual .env values and your PHP configuration with phpinfo() in a safe debug route—never in production.
- Double-check docker-compose.yml for correct service names, network aliases, and exposed ports.
- For debugging, set SELinux/AppArmor to 'permissive' mode—set back to 'enforcing' for production.
Best Practices for Laravel Database Connections
To avoid SQLSTATE HY000 connection refused issues in the future:
- Use environment variables, not hardcoded values - Automate .env validation in CI pipelines - Prefer named Docker services and explicit networks - Avoid relying only on localhost sockets if deploying to containers - Document and share any unusual network or firewall rules within your team
Conclusion: No More Connection Refused Errors
Laravel SQLSTATE HY000 2002 connection refused can be frustrating, but 90% of the time it’s a config or network oversight. Methodically checking each step—from the MySQL/MariaDB service status, through .env tweaks, to container networking—usually resolves things. Once you’ve fixed this once or twice, you’ll spot it immediately. Happy coding!
Frequently asked questions
How do I fix SQLSTATE[HY000] [2002] Connection refused in Laravel?
First, confirm MySQL/MariaDB is running. Next, double-check your .env DB_HOST and DB_PORT match your server. Clear Laravel’s config cache. If you’re using Docker, set DB_HOST to your database service name, not localhost or 127.0.0.1.
Should I use localhost or 127.0.0.1 for Laravel's DB_HOST?
Use 127.0.0.1 unless you specifically want to use Unix sockets. 'localhost' may trigger socket mode on many systems, which only works if MySQL/MariaDB supports it and PHP is configured to use the correct socket path.
Why does Laravel still refuse connection after I fixed .env?
You probably need to clear Laravel’s config cache with artisan commands. Also, make sure there are no typos in variable names and that MySQL/MariaDB is running and listening on the correct address.
How can I debug Laravel SQLSTATE error in Docker?
Check that DB_HOST matches your docker-compose service name for MySQL/MariaDB. Make sure the port is exposed and networks are correct. Also, verify you can connect via CLI from within your app’s container.
Does restarting MySQL affect active Laravel sessions?
Restarting MySQL/MariaDB interrupts active DB connections, including open transactions and any session data stored in the DB. Schedule restarts for off-peak hours on production systems.