`psql: FATAL: role does not exist` or `password authentication failed` Usually Means You Are Connecting with the Wrong User, the Wrong DB, or the Wrong Assumption About How Postgres Auth Is Set Up
A practical guide to fixing common Postgres login failures by checking the target host, user, database, container context, and auth configuration instead of repeatedly retrying the same broken credentials.
Why this issue matters: Postgres auth errors are often treated like password problems when the real issue is that the client is aiming at the wrong host, the wrong role, or a database setup that never created the user you think exists.
Two common failures are:
psql: error: connection to server at "localhost" failed: FATAL: role "app" does not existand:
FATAL: password authentication failed for user "postgres"These look similar, but they mean different things.
Understand the difference
role does not existmeans the username is unknown to that Postgres serverpassword authentication failedmeans the role exists, but auth failed
That distinction matters because one calls for role inspection, the other calls for credential or auth-method inspection.
First verify where you are connecting
echo $DATABASE_URL
psql -h localhost -U postgres -d postgresIf you have multiple Postgres instances running:
- local service
- Docker container
- remote dev DB
then half the battle is confirming which one is answering.
Check listeners:
lsof -iTCP:5432 -sTCP:LISTEN -n -P
docker ps --format "table {{.Names}}\t{{.Ports}}"Inspect roles from a known-good account
If you can log in with any existing superuser:
\duThat shows whether the expected role exists.
To create a missing role:
CREATE ROLE app WITH LOGIN PASSWORD 'strong-password';To create a database too:
CREATE DATABASE appdb OWNER app;Docker-specific confusion
If your container sets:
POSTGRES_USER=myuser
POSTGRES_PASSWORD=secret
POSTGRES_DB=mydbthose variables usually only initialize the database on first creation. If the volume already existed, changing env vars later does not recreate users automatically.
That is why people keep changing compose values and wondering why old credentials still rule the world.
If the role exists but password fails
Reset it from a privileged session:
ALTER ROLE app WITH PASSWORD 'new-secret';Then verify the client is actually using that user:
psql -h localhost -U app -d appdbFinal recommendation
Treat Postgres login errors as connection-truth problems. Confirm which server answered, whether the role exists there, and whether the credentials match that specific instance. Most wasted time comes from retrying the right password against the wrong database.