This MySQL authentication error (1045) occurs when connection credentials are rejected during the authentication phase. The error indicates MySQL received the password but rejected it due to authentication method mismatch, incorrect password, wrong user account, socket authentication plugin, or permissions issue. Common on fresh installations with auth_socket authentication or when password authentication is not properly configured.
Error 1045 "Access denied" is MySQL's standard authentication failure response. This error occurs during the connection verification stage when: 1. **Authentication Plugin Mismatch**: Modern MySQL (especially on Ubuntu/Debian) defaults to unix_socket authentication for localhost connections. The auth_socket plugin verifies the Linux system username matches the MySQL username, bypassing password checks. When a password is supplied, the authentication method may reject it if the system username doesn't match. 2. **Incorrect Password**: The password provided doesn't match the stored hash for that user account. MySQL compares the encrypted supplied password against the authentication_string column in the mysql.user table. 3. **Wrong User Account**: No user account exists with the specified username@host combination. MySQL looks for exact matches - "root"@"localhost" is different from "root"@"127.0.0.1" or "root"@"%". 4. **Temporary Password Requirement**: Fresh MySQL 5.7+ installations generate a temporary root password logged in the error log. The default password must be changed before normal authentication works. 5. **Account Locked or Disabled**: The user account may be locked (ACCOUNT LOCK) or disabled (ALTER USER ... ACCOUNT UNLOCK/LOCK). Unlike connection errors (2003), this error means the network path succeeded but credentials were rejected at the MySQL authentication layer.
Check the authentication plugin being used for the root user:
# Log in as system root (requires sudo)
sudo mysql -u root
# Check the authentication plugin for root@localhost
SELECT user, host, plugin, authentication_string FROM mysql.user WHERE user = 'root';
# Output will show one of these plugins:
# - auth_socket (no password, uses system username)
# - mysql_native_password (password-based)
# - caching_sha2_password (MySQL 8.0+ default, requires SSL or temp password change)
# - unix_socket (similar to auth_socket)If the plugin is auth_socket or unix_socket and you want password authentication, you need to change it (see Step 2).
If auth_socket or unix_socket is enabled, switch to mysql_native_password or caching_sha2_password:
# Log in with sudo (bypasses password requirement for socket auth)
sudo mysql -u root
# For MySQL 5.7+ or MariaDB, use ALTER USER with mysql_native_password:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_strong_password';
# For MySQL 8.0+, you can also use the default caching_sha2_password:
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'your_strong_password';
# Apply changes immediately
FLUSH PRIVILEGES;
# Verify the change
SELECT user, host, plugin FROM mysql.user WHERE user = 'root';
# Exit MySQL
EXIT;
# Now test password authentication
mysql -u root -p
# Enter your password when promptedIf you get an error about auth_socket not supporting passwords, you're still using that plugin - re-run the ALTER USER command.
MySQL 5.7+ generates a temporary root password on first run:
# Find the temporary password in MySQL error log
sudo grep 'temporary password' /var/log/mysql/error.log
# or
sudo grep 'temporary password' /var/log/mysqld.log
# or
sudo journalctl -u mysql -n 100 | grep 'temporary'
# Output format: [Note] A temporary password is generated for root@localhost: xxxxxxxxxxxx
# Use that temporary password to log in
mysql -u root -p
# Paste the temporary password
# MySQL will require you to change the password on first login:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'your_new_permanent_password';
# If you get error "Your password does not satisfy the password policy requirements":
# Either create a stronger password (8+ chars, uppercase, lowercase, number, special char)
# Or temporarily reduce password validation:
SET GLOBAL validate_password.policy=LOW;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';
SET GLOBAL validate_password.policy=MEDIUM;
# After password change, you can log out and back in
EXIT;
mysql -u root -p
# Enter your new passwordIf you can't find the temporary password, use the skip-grant-tables method (Step 4).
MySQL authenticates based on both username AND host - they must both match:
# Log in (using socket auth with sudo if needed)
sudo mysql -u root
# List all root user accounts
SELECT user, host, authentication_string FROM mysql.user WHERE user = 'root';
# Check which one matches your connection attempt
# If connecting to localhost, look for 'root'@'localhost' or 'root'@'127.0.0.1'
# If connecting to a specific IP, look for 'root'@'that.ip.address'
# If connecting remotely, look for 'root'@'%' or 'root'@'hostname'
# If no matching account exists, create one:
CREATE USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
# Or grant privileges to existing user:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
# Test the connection
EXIT;
mysql -u root -p -h localhost
# Enter your passwordHost specificity matters - localhost, 127.0.0.1, and the machine hostname are different from MySQL's perspective.
If you've lost access and can't authenticate, reset the password by temporarily disabling authentication:
# Stop MySQL server
sudo systemctl stop mysql
# or
sudo service mysql stop
# Edit the MySQL configuration file
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
# or
sudo nano /etc/my.cnf
# Find the [mysqld] section and add skip-grant-tables under it:
[mysqld]
skip-grant-tables
# Save and exit (Ctrl+O, Enter, Ctrl+X in nano)
# Start MySQL without grant table validation
sudo systemctl start mysql
# Connect without a password (authentication is skipped)
mysql -u root
# Flush privileges to reload authentication system
FLUSH PRIVILEGES;
# Set a new password
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'new_password';
# Exit MySQL
EXIT;
# Remove skip-grant-tables from config file
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
# Delete or comment out the skip-grant-tables line
# Restart MySQL with authentication enabled
sudo systemctl restart mysql
# Test with new password
mysql -u root -p
# Enter the new passwordWARNING: skip-grant-tables is a significant security risk. Remove it immediately after resetting the password. Never leave MySQL running with this setting in production.
Special characters in passwords can cause authentication issues if not properly escaped:
# If your password contains special characters like @, $, !, & etc.
# When connecting from command line, the password may need escaping or quoting:
# Method 1: Don't use -p with password inline (more secure)
mysql -u root -p
# Then enter password at the prompt
# Method 2: URL-encode special characters in connection strings
# @ becomes %40
# $ becomes %24
# ! becomes %21
# For application connection strings, check documentation for escaping:
# PHP: $dsn = "mysql:host=localhost;user=root;password=your_password";
# Python: mysql.connector.connect(user='root', password='your_password')
# Node.js: mysql.createConnection({user: 'root', password: 'your_password'})
# Test with a simple password first (alphanumeric only):
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'SimplePassword123';
FLUSH PRIVILEGES;
# Test connection
mysql -u root -p
# If this works, then special characters in your password were the issueProduction passwords should be strong, but ensure your application handles escaping properly.
Authentication can fail if the account is locked or lacks basic privileges:
# Log in with sudo if needed
sudo mysql -u root
# Check account status and details
SELECT user, host, authentication_string, Account_locked FROM mysql.user WHERE user = 'root';
# Also check mysql.user table structure to see all relevant columns
DESC mysql.user;
# If account is locked (ACCOUNT LOCK status shows 'Y'), unlock it:
ALTER USER 'root'@'localhost' ACCOUNT UNLOCK;
# Ensure root has all privileges
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
# Verify the grants
SHOW GRANTS FOR 'root'@'localhost';
# Check if password_expired is set (may require reset)
SELECT user, host, password_expired FROM mysql.user WHERE user = 'root';
# If password is expired, change it
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'new_password';Locked accounts or expired passwords will cause authentication failures even with correct credentials.
Understanding MySQL authentication involves several advanced concepts:
1. Authentication Plugin Differences: MySQL 8.0 defaults to caching_sha2_password which uses SHA-256 hashing. Older mysql_native_password uses MySQL's native hashing. They are not compatible - connections must use matching plugin. When upgrading from MySQL 5.7 to 8.0, existing mysql_native_password accounts continue working, but new accounts use caching_sha2_password.
2. Socket Authentication on Linux: Ubuntu/Debian default fresh installations to auth_socket for root, which validates that the Linux system user matches the MySQL username. Running "mysql" as root user succeeds without a password. Running as a non-root user fails. This is actually more secure than password-based authentication.
3. Host Matching Logic: MySQL matches user accounts using "root"@"localhost" differently than "root"@"127.0.0.1". Localhost resolves through Unix socket, while 127.0.0.1 uses TCP/IP. MariaDB 10.4+ treats them identically, but MySQL maintains the distinction.
4. Password Hashing and Expiration: MySQL 5.7.4+ supports password expiration policies. Expired passwords require reset before use. The password_expired column in mysql.user table controls this. Use REQUIRE PASSWORD CHANGE clause in ALTER USER to force resets.
5. Failed Login Tracking: MySQL 8.0.19+ supports account password history and failed login tracking. Excessive failed logins can temporarily lock accounts. Check FAILED_LOGIN_ATTEMPTS and PASSWORD_LOCK_TIME in mysql.user table.
6. Connection Limits per User: The max_user_connections variable limits simultaneous connections per user. If a user reaches their limit, new connections receive error 1203 "User account has been locked". This differs from 1045 but can appear similar in applications.
7. Replication and User Accounts: When using MySQL replication, the replication user must exist on both primary and replica servers with appropriate privileges. Replication connection failures often manifest as 1045 errors.
8. Upgrading MySQL Versions: Major version upgrades (especially 5.7 to 8.0) may change default authentication plugins. After upgrade, run "mysql_upgrade" utility and verify authentication settings. Some accounts may need plugin changes for compatibility.
9. Docker and Container Gotchas: In Docker containers, the default root user may use unix_socket authentication. The container's init script may need to create password-authenticated users. Use environment variables (MYSQL_ROOT_PASSWORD) to set passwords automatically during container creation.
10. Testing Connection Details: When debugging authentication failures, use MySQL connection utilities with verbose output: "mysql -u root -p -v", or application-specific connection debugging (e.g., PHP's mysqli_connect_error()). Logging queries with "SET GLOBAL general_log=1" shows authentication attempts in the log file.
EE_WRITE (3): Error writing file
How to fix "EE_WRITE (3): Error writing file" in MySQL
CR_PARAMS_NOT_BOUND (2031): No data supplied for parameters
How to fix "CR_PARAMS_NOT_BOUND (2031): No data supplied for parameters" in MySQL
CR_DNS_SRV_LOOKUP_FAILED (2070): DNS SRV lookup failed
How to fix "CR_DNS_SRV_LOOKUP_FAILED (2070): DNS SRV lookup failed" in MySQL
ERROR 1146: Table 'database.table' doesn't exist
How to fix "ERROR 1146: Table doesn't exist" in MySQL
ERROR 1040: Too many connections
How to fix "ERROR 1040: Too many connections" in MySQL