Fix PostgreSQL 'FATAL: password authentication failed' for User

beginner๐Ÿ˜ PostgreSQL2026-03-19| PostgreSQL 12โ€“16, Linux (Ubuntu/Debian/RHEL), macOS, Windows โ€” psql CLI and application connection strings

Error Message

FATAL: password authentication failed for user "your_user"
#postgresql#authentication#password#pg_hba.conf

TL;DR

You hit FATAL: password authentication failed for user "your_user". Run through this checklist before digging deeper:

  • Wrong password โ†’ reset it with ALTER USER your_user WITH PASSWORD 'newpassword';
  • pg_hba.conf auth method mismatch โ†’ align md5 vs scram-sha-256
  • User has no password set โ†’ set one explicitly
  • Connection string typo โ†’ double-check your app config

What's Actually Happening

PostgreSQL rejected the password your client sent. Three distinct causes lead here, and each needs a different fix. Blindly resetting the password only solves one of them โ€” figure out which case you're in first.

Reason 1: The Password Is Simply Wrong

Most common cause. The password in your connection string doesn't match what PostgreSQL has stored for that user. This also bites you after server migrations โ€” for example, if you pg_dumpall'd roles but then manually reset the password on the new server while the app still carries the old value in its config.

Reason 2: Authentication Method Mismatch in pg_hba.conf

pg_hba.conf controls how each connection is authenticated. If the file says md5 but the password was stored as scram-sha-256 (the default since PostgreSQL 14), the login fails even when the password is 100% correct. The reverse works the same way โ€” wrong direction, same error.

Reason 3: User Has No Password or Doesn't Exist

A user created with CREATE USER myuser; โ€” no password clause โ€” can't authenticate via password-based methods. PostgreSQL returns this same opaque error instead of something like "no password set," which is frustrating but consistent.

Fix Approaches

1. Reset the User's Password

Connect as the postgres superuser. On Linux this usually works via peer authentication:

sudo -u postgres psql

Then reset the password:

ALTER USER your_user WITH PASSWORD 'your_new_password';

Exit with \q and test the connection:

psql -U your_user -h 127.0.0.1 -d your_database -W

The -W flag forces a password prompt, confirming you're testing the actual credential rather than falling through to peer auth silently.

2. Fix the pg_hba.conf Authentication Method

First, find your pg_hba.conf location:

sudo -u postgres psql -c "SHOW hba_file;"

On Ubuntu/Debian with PostgreSQL 15, this is typically /etc/postgresql/15/main/pg_hba.conf. Open it and find the line matching your connection type:

# TYPE  DATABASE  USER    ADDRESS         METHOD
host    all       all     127.0.0.1/32    md5

Running PostgreSQL 14+ with default settings? The stored hash is scram-sha-256. Change the method to match:

host    all       all     127.0.0.1/32    scram-sha-256

Need to support older clients that only speak md5? Keep the method as md5 but re-hash the password in md5 format explicitly:

-- Run as postgres superuser:
SET password_encryption = md5;
ALTER USER your_user WITH PASSWORD 'your_password';

After any pg_hba.conf change, reload PostgreSQL โ€” no full restart required:

sudo systemctl reload postgresql

3. Verify the User Exists and Has a Password Set

Check whether the user exists at all:

sudo -u postgres psql -c "\du your_user"

No output means the user doesn't exist. Create them:

CREATE USER your_user WITH PASSWORD 'your_password';

Already exists but you're not sure if a password is stored? Query pg_shadow (superuser only):

SELECT usename, passwd IS NOT NULL AS has_password
FROM pg_shadow
WHERE usename = 'your_user';

If has_password returns f, run the ALTER USER command above to set one.

4. Quick Debug: Temporarily Use Trust Authentication

Not sure whether the problem is the password or the auth method? You can temporarily bypass password checks for your user on localhost. Add this line to pg_hba.conf above the existing host lines:

host    all       your_user   127.0.0.1/32    trust

Reload and connect. If it works, the user and database config are fine โ€” the issue is purely the password or hash method. Remove this line immediately after testing. Trust auth in production is a serious security hole.

Verify the Fix Worked

Test with an explicit password prompt:

psql -U your_user -h 127.0.0.1 -d your_database -W

For app connections, check your connection pool logs. PgBouncer, Sequelize, and Django's connection layer all pick up fresh credentials on the next attempt โ€” you usually don't need to restart the whole app, just wait for the pool to cycle. If you store the connection string in environment variables, confirm the updated value is actually loaded into the running process, not just written to disk.

You can also test from inside your app's environment directly:

psql "postgresql://your_user:your_password@127.0.0.1:5432/your_database"

Tips for Preventing This

The most common repeat offender in team setups: someone sets a database password once, doesn't document it, and later a different developer grabs it from Slack or a wiki โ€” typos happen, values drift out of date. Set strong random passwords from day one and store them in a secrets manager or a gitignored .env file, not in chat.

Need a random password right now? ToolCraft's Password Generator runs entirely in your browser with no server-side processing โ€” useful when you want something genuinely random without installing anything.

One more thing to watch after major version upgrades: jumping from PostgreSQL 13 to 16 changes the default password_encryption from md5 to scram-sha-256. Existing hashes carry over as-is, but any password reset after the upgrade uses the new format. You end up with a mix of hash types and a guaranteed auth mismatch for whoever gets reset first. Run an audit after any major version jump to catch this early.

Related Error Notes