MySQL Error: 'ERROR 1044 (42000): Access denied for user to database' — Cause, Fix, and Troubleshooting Guide
Fix MySQL ERROR 1044 (42000) Access denied for user to database: missing GRANTs, wrong host account, and forgotten FLUSH PRIVILEGES.
- #mysql
- #mariadb
- #database
- #troubleshooting
Stuck on this MySQL error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
ERROR 1044 (42000) means the user authenticated successfully but does not hold the privileges required to use the target database. The credentials are valid — the authorization is not:
ERROR 1044 (42000): Access denied for user 'app'@'localhost' to database 'reporting'
This is different from ERROR 1045, which is a login (authentication) failure. With 1044 you are already connected; MySQL is refusing an operation because the account has no grant on that schema, or the grant was issued to a different user@host combination than the one you actually connected as.
Symptoms
USE reporting;or a query against a schema fails with 1044 while the same account can query other databases.- A
CREATE DATABASE/DROP DATABASEfails even though login works. - An app that “worked yesterday” breaks after a credential rotation or a host/IP change.
SHOW GRANTSfor the account lists no privilege on the schema in question.
Common Root Causes
1. No grant on the target database
The account simply has no privileges on that schema.
SHOW GRANTS FOR 'app'@'localhost';
+-------------------------------------------------+
| Grants for app@localhost |
+-------------------------------------------------+
| GRANT USAGE ON *.* TO `app`@`localhost` |
| GRANT ALL PRIVILEGES ON `appdb`.* TO `app`@... |
+-------------------------------------------------+
USAGE means “no privileges.” The account can log in but touch nothing outside appdb.
2. The grant is on a different host pattern
MySQL identity is user@host. A grant to 'app'@'10.0.%' does nothing for a connection that resolves to 'app'@'localhost'.
3. Privileges granted but never flushed
Editing mysql.* tables directly (rather than GRANT) requires FLUSH PRIVILEGES before the change takes effect.
4. Trying to create a database without CREATE
A user with rights only on existing schemas cannot CREATE DATABASE — that needs a global CREATE privilege.
How to diagnose
Confirm exactly who you are connected as, then inspect that identity’s grants:
SELECT CURRENT_USER(), USER();
SHOW GRANTS FOR CURRENT_USER();
CURRENT_USER() shows the account MySQL matched you to (may differ from what you typed); USER() shows what you requested. Compare against the schema you need:
SELECT * FROM information_schema.SCHEMA_PRIVILEGES
WHERE GRANTEE = "'app'@'localhost'";
Fixes
Grant the needed privileges on the specific database (least privilege first):
GRANT SELECT, INSERT, UPDATE, DELETE ON reporting.* TO 'app'@'localhost';
FLUSH PRIVILEGES;
If the app connects from a pod network rather than localhost, grant to the correct host pattern:
GRANT SELECT, INSERT, UPDATE, DELETE ON reporting.* TO 'app'@'10.0.%';
FLUSH PRIVILEGES;
To allow creating databases (use sparingly):
GRANT CREATE ON *.* TO 'app'@'localhost';
Verify the result:
SHOW GRANTS FOR 'app'@'localhost';
What to watch out for
- Grant to the exact
user@hostthe connection resolves to — checkCURRENT_USER(), not what you typed. A duplicate anonymous''@'localhost'account can silently win the match on some installs. - Prefer per-database grants (
reporting.*) over*.*; broadALL PRIVILEGES ON *.*is a common over-grant that turns a scoping bug into a security problem. - After any manual edit to
mysql.user/mysql.db, runFLUSH PRIVILEGESor the change is invisible until restart. - Wildcards matter:
reporting.*(all tables) is not the same asreporting(a table literally named that).
Related
- ERROR 1045: Access denied for user — the authentication-failure sibling of this error.
- ERROR 1142: command denied to user — a specific operation is denied even when database access is allowed.
- ERROR 1698: Access denied (auth_socket) — plugin-based auth refusing root on localhost.
Fixed it? Get 500 MySQL & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.