psql: FATAL: Peer authentication failed for user "postgres"
The error fires when PostgreSQL's peer auth check compares the OS username to the database role and they differ — common after sudo-ing into psql or in local dev. Fix it by matching users, or by switching the local auth method to scram-sha-256 with a real password.
You fire up local PostgreSQL, type psql -U postgres, and the connection dies with:
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432"
failed: FATAL: Peer authentication failed for user "postgres"The Stack Overflow thread Q18664074 has the diagnosis: peer authentication compares the OS username to the database role, and they don't match. You ran psql as your own OS user (e.g. mahdi) but asked to connect as role postgres. Peer auth says no.
This is a local-dev issue, not a production one — peer auth is only the default for local connections in pg_hba.conf. Here are the two correct fixes.
Fix 1 — Connect as the matching OS user#
The cleanest fix: become the user PostgreSQL expects.
sudo -u postgres psqlpostgres is both the OS account the server runs as and the default superuser role. Peer auth now sees OS user postgres connecting as role postgres — match, allowed.
If you need your own database role, create it and connect as yourself:
sudo -u postgres createuser --superuser $USER
sudo -u postgres createdb $USER
psql # now peer auth matches: OS user mahdi -> role mahdiFix 2 — Switch the local method to scram-sha-256#
If you want to connect as role postgres from your own OS user with a password (common for app dev), change the auth method. The order matters: set the password while peer auth still lets you in, then switch the method. The steps below were reproduced on Debian 12 with the distribution's PostgreSQL 15.19 package on 2 October 2026.
Step 1 — Set a password for the role, and locate pg_hba.conf#
Peer auth never used a password, so the role likely has none. The password authentication docs are explicit: if no password has been set up for a user, password authentication will always fail for that user. Set it now, while sudo -u postgres psql still works through peer:
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'a-strong-dev-password';"
sudo -u postgres psql -c 'SHOW hba_file;'In the reproduction, switching the method first and setting the password afterwards locked the postgres account out of its own socket: sudo -u postgres psql then failed with fe_sendauth: no password supplied, and with any guessed password with password authentication failed for user "postgres".
Step 2 — Edit every local line that matches the role#
PostgreSQL uses the first pg_hba.conf record that matches the connection type, database and user; the pg_hba.conf docs state there is no fall-through to later records. On Debian and Ubuntu the packaged file has a dedicated line for the postgres role above the general one. This is the Debian 12 default:
local all postgres peer
local all all peer
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256Changing only the local all all line has no effect for role postgres: in the reproduction, psql -U postgres run as another OS user still failed with Peer authentication failed for user "postgres", because the first line matched. Change both:
local all postgres scram-sha-256
local all all scram-sha-256Setting the method to trust makes the error go away by disabling auth entirely — any local user can connect as any role, including the superuser. Fine on an isolated throwaway VM, dangerous on any shared or developer machine. Use scram-sha-256 and a real password.
Step 3 — Reload PostgreSQL#
sudo systemctl reload postgresqlReload is enough — pg_hba.conf changes do not need a full restart.
Step 4 — Check over the socket, not over TCP#
Run psql -U postgres with no -h: it connects over the Unix socket, which is what the local lines govern. It now prompts for the password and succeeds; a wrong password fails with password authentication failed for user "postgres".
Do not test with psql -U postgres -h localhost. That connects over TCP and matches the host lines, which are already scram-sha-256 on Debian 12: in the reproduction it succeeded with the password before pg_hba.conf was touched, so it proves nothing about the local edit.
Supabase local dev#
Supabase's local stack (the supabase CLI with supabase start) runs Postgres in a container with its own auth setup — peer auth is not the issue there. The usual gotchas:
- Use the exact database URL that
supabase statusprints — by defaultpostgresql://postgres:postgres@127.0.0.1:54322/postgres, on port54322, not5432. - Studio runs on
54323. Use the DB port, not the studio port, in your connection string. supabase stopkeeps your local data: the CLI docs state that local data "are backed up to docker volume", and onlysupabase stop --no-backupdeletes the data volumes. A password you changed withALTER USERtherefore survives a stop/start — restarting is not a way to reset it.
Once the database connects, the next problems are usually in the app: RLS, keys, cookies and pooling are covered in common Next.js + Supabase production mistakes.
Why peer auth exists#
Peer auth lets PostgreSQL delegate authentication to the OS: if you are already logged in as user mahdi on a secure multi-user box, that is proof enough — no password to leak. It is secure and zero-config when the OS user and PG role match by convention. The error is the system correctly refusing a mismatch, not a bug.
Common mistakes#
trustto make it stop — disables auth; usescram-sha-256instead.- Editing the wrong
pg_hba.conf— there can be several (Debian vs Homebrew vs Docker). Confirm withSHOW hba_file;before editing. - Forgetting to reload —
pg_hba.confis re-read on reload, not on every connection; runsystemctl reload postgresql. - Setting the password last — once the matching
localline isscram-sha-256, a role with no password cannot log in at all (fe_sendauth: no password supplied, orpassword authentication failed), including throughsudo -u postgres psql. Set it first. - Editing only the
local all allline on Debian/Ubuntu — thelocal all postgresline above it still matches first. - Port confusion in Supabase local — DB is
54322, not5432.
Official references: PostgreSQL — Client Authentication (pg_hba.conf), Auth Methods — Peer Authentication. For a related connection issue on Apple Silicon, see Prisma can't reach database server.
The host-connection equivalent: ident authentication and pg_ident.conf#
Everything above concerns peer auth, which only applies to local connections — the
ones made over a Unix domain socket, with no host or port in the connection string.
There's a separate but conceptually identical method for TCP connections
(host lines in pg_hba.conf): ident. Where peer asks the local kernel who owns
the process making the socket connection, ident asks a remote ident service
(defined by RFC 1413) running on the connecting machine who owns that TCP connection.
It fails for the same underlying reason — the identity PostgreSQL is told doesn't match
the role being requested — but it produces a distinct error, Ident authentication failed for user "...":
# pg_hba.conf — host line using ident
# TYPE DATABASE USER ADDRESS METHOD
host all all 192.168.1.0/24 identBoth peer and ident accept a map= option on the line; only then does PostgreSQL
consult pg_ident.conf for user-name mapping, letting an OS user log in as a
differently-named PostgreSQL role (user name maps).
Without a map, the OS name must equal the role name. In practice, ident over
the network is rare today: most production setups use scram-sha-256 for host
connections precisely to avoid depending on a remote identd service most systems
don't run. If a host line is set to ident and nothing is listening on the remote
machine's ident port, the connection fails outright rather than falling through to a
different check — switching that line to scram-sha-256, the same method Fix 2 above
uses for local, resolves it identically. Once a host line uses password auth, the
connection can still fail on a separate check afterward — see
Fix: password authentication failed for user "postgres"
for that follow-on error.
Peer auth inside a Docker container#
With the official postgres Docker image, docker exec -it <container> psql -U postgres
works, but not because of a user match. The image's Dockerfile sets no USER, so
docker exec runs as root; it works because, as the image documentation
says, the image sets up trust authentication locally. Checked on postgres:18 on
2 October 2026: whoami inside docker exec printed root, the generated
pg_hba.conf starts with these lines, and even docker exec -u nobody … psql -U postgres
connected:
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
host all all all scram-sha-256So a peer error inside a container means the server was not set up by the official
image's entrypoint, typically an image that installs the distribution's postgresql
package, which keeps the Debian peer lines shown in Fix 2. Apply Fix 2 inside that
container, or connect from the app over TCP (host=db port=5432, the compose service
name) with a password; from another container, the last line above means a password
is required. For the container networking model this depends on, see
Docker Tutorial 2026: Dev Environment with Compose.
Frequently Asked Questions
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
One email a month — the latest explained errors
What the site published that month — mostly Next.js, Supabase and Node errors, explained. You confirm by email; unsubscribe any time in one click.
Continue Reading
FATAL: password authentication failed for user "postgres"
The error fires when PostgreSQL rejects the password the client sent — common when a role never got a password, when an old md5 hash meets a scram-sha-256 rule in pg_hba.conf, or when a Docker volume still holds an older password. Set the password with ALTER USER, then check the hash type.
How to Change a PostgreSQL User Password (Supabase)
`ALTER ROLE alice WITH PASSWORD 'newpass';` is the SQL. The psql `\password` prompt avoids logging the cleartext. In Supabase the `postgres` role password is reset from the Dashboard, not SQL. Here is each method, the scram-sha-256 default, and the three things that break after a password change.
psql command not found: install the client or fix PATH
The error fires when the shell cannot locate the psql binary — either PostgreSQL is not installed (only libpq-dev or a GUI client is), or it is installed but its bin directory is not on PATH. Fix it by installing the postgresql-client package on Linux, libpq via Homebrew on macOS, PostgreSQL itself (choco on Windows), or appending the bin directory to PATH.


