Skip to content
Nilay Kabariya

Entry No.078·Database·Updated ·5 min read

Postgres password authentication failed, but the password is right

Changed POSTGRES_PASSWORD in docker-compose and the old one still works? The volume keeps it. Five causes of this Postgres error, reproduced with postgres:18.

by Nilay#postgres#docker#prismaDATABASE

The error, verbatim

Jump to the fix ↓
psql: error: connection to server at "localhost" (::1), port 5432 failed: FATAL:  password authentication failed for user "postgres"
✓ Reproduced on Ubuntu 24.04 (GitHub Actions runner)

Tested on

Postgres
18.6 (official Docker image)
Clients
psql 16.15, node-postgres 8.23.1, Prisma 7.10.1
Docker
Docker Compose v2
OS
Ubuntu 24.04 (GitHub Actions runner)

✓ Last re-run on GitHub Actions · see the run · all repros

Contents
  1. Step 1: read the server’s side01
  2. You changed the password in docker-compose.yml02
  3. The user doesn’t exist03
  4. Quotes in an env file04
  5. Another Postgres on the same port05
  6. Special characters in the connection URL06
  7. How the error looks in Node and Prisma07
  8. How this was tested08

The most common version of this has nothing to do with typing: you changed POSTGRES_PASSWORD in docker-compose.yml, restarted, and the new password fails while the old one still works. POSTGRES_PASSWORD is only read the first time the container starts with an empty data folder, and the volume keeps the old password. Postgres gives the same message for that, for a user that doesn’t exist and for a different server on the same port, on purpose, so an attacker can’t tell which part was right.

I caused it five different ways with the official postgres:18 image. Every time, the client said exactly the same thing:

What was actually wrong What the client said
The password in docker-compose.yml was changed after the first start password authentication failed for user "postgres"
POSTGRES_USER was added after the first start password authentication failed for user "admin"
The env file had quotes around the password, used with docker run --env-file password authentication failed for user "postgres"
Another Postgres was already running on port 5432 password authentication failed for user "postgres"
Plain wrong password password authentication failed for user "postgres"

Step 1: read the server’s side

The client only gets the short version. The server writes the reason to its own log, one line under the error:

docker logs <container> 2>&1 | grep -E "FATAL|DETAIL"

With Compose, docker compose ps -q db prints the container ID. What the DETAIL line said in my tests:

You changed the password in docker-compose.yml

This is the most common one. POSTGRES_PASSWORD only does anything the first time the container starts with an empty data folder. After that, the password lives in the data, which sits in a volume that outlives the container.

I started Compose with password first, ran docker compose down, changed it to second and ran docker compose up again. The new password failed and the old one still worked. The container log said why, on startup:

PostgreSQL Database directory appears to contain a database; Skipping initialization

To keep your data, change the password inside the running container. The container’s own psql connects over a local socket that doesn’t ask for a password:

docker exec <container> psql -U postgres -c "ALTER USER postgres PASSWORD 'second'"

If the data doesn’t matter (a fresh dev database), delete the volume so the next start initializes again with the new password:

docker compose down -v
docker compose up -d

The user doesn’t exist

Same trap, different variable. I added POSTGRES_USER: admin to a Compose file whose volume already existed. Postgres skipped initialization, so admin was never created, and the client said password authentication failed for user "admin". Only the server log said Role "admin" does not exist.

Create the user yourself, inside the container:

docker exec <container> psql -U postgres -c "CREATE USER admin WITH PASSWORD 'second' SUPERUSER"

Or, for a throwaway database, delete the volume as in the section above so the next start creates admin.

Quotes in an env file

My .env file had POSTGRES_PASSWORD="secret". The same file gave two different passwords:

Started with Password that worked
docker compose with env_file: .env secret
docker run --env-file .env "secret", quotes included

Compose removes the quotes. docker run --env-file keeps them as part of the password.

Write the line without quotes when you use docker run --env-file:

POSTGRES_PASSWORD=secret

If the database already started with the quoted value, the quotes are now part of its password. Connect with them once and change it:

PGPASSWORD='"secret"' psql -h localhost -U postgres -c "ALTER USER postgres PASSWORD 'secret'"

Another Postgres on the same port

The runner had its own Postgres 16 installed as a system service. With that running, docker run -p 5432:5432 postgres:18 didn’t start at all:

docker: Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint n1 (...): failed to bind host port for 0.0.0.0:5432

If you miss that line, everything after it goes to the other server. The password I gave the container failed, and the container log stayed empty because the connection never reached it.

Check that your container is actually running:

docker ps

Mine wasn’t in the list. docker ps -a showed it with the status Created: it was made, but never started. Then either stop the other server, or publish the container on a different port and use that port in your connection string:

docker run -d -e POSTGRES_PASSWORD=dockerpw -p 5433:5432 postgres:18

I tested this on Linux only. The setup that usually leads here on Windows (the PostgreSQL installer’s service on 5432 plus Docker Desktop) wasn’t part of this test.

Special characters in the connection URL

A password with @ or # in a URL doesn’t usually give this error. It breaks the URL first, so the error looks unrelated. With the password p@ss#w0rd written as-is:

Client Error
psql could not translate host name "ss#w0rd@localhost" to address
node-postgres 8.23.1 getaddrinfo EAI_AGAIN ss
Prisma 7.10.1 P1001: Can't reach database server at `ss:5432`

Everything after the @ in the password was read as the host.

Percent-encode those characters in the URL: @ is %40, # is %23.

postgresql://postgres:p%40ss%23w0rd@localhost:5432/postgres

How the error looks in Node and Prisma

The same failure, wrong password and all, comes out differently depending on the client:

  • node-postgres: password authentication failed for user "postgres", with err.code set to 28P01. Use that code to catch it.
  • Prisma 7 CLI: Error: P1000 Authentication failed against database server, the provided database credentials for `postgres` are not valid.

A missing password is a different error. When the password was undefined, for example from an environment variable that wasn’t loaded, node-postgres threw SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string before the server could check anything.

How this was tested

Ubuntu 24.04 on a GitHub Actions runner, October 18, 2026. The postgres:18 image (18.6) ran through Docker Compose v2 and docker run, and the runner’s preinstalled Postgres 16 played the second server. Each case was checked with psql 16.15, node-postgres 8.23.1 and Prisma 7.10.1. Every message above is the real output, from the test script.

— N.K., end of entry No.078

Useful? Pass it on:Post on XFollow @EmotionalMatter

Related entries

  1. No.050

    Prisma P1001: Can't reach database server at localhost:5432

    P1001 prints the same words for five different problems, Docker and Supabase included. Each one reproduced, plus a one-line check that tells them apart.

    > Error: P1001: Can't reach database server at `localhost:5432`

    DATABASE5 min
  2. No.079

    Prisma P2002 on Prisma 7: e.meta.target is now undefined

    On Prisma 7, P2002 names the constraint on Postgres and e.meta.target is undefined on Postgres and SQLite. Where the field went, and the upsert race.

    > PrismaClientKnownRequestError:

    DATABASE4 min
  3. No.053

    Prisma P1012: "url is no longer supported in schema files"

    Prisma 7 rejects the url line every older tutorial uses. Reproduced on 7.10.0, plus directUrl, the .env trap and the adapter error that comes next.

    > Error: Prisma schema validation - (get-config wasm)

    DATABASE3 min

Post card · Every Sunday

What broke this week.

One email on Sundays: the Node, TypeScript, Python and AI SDK releases that broke builds that week, each one reproduced, with a link to the fix that worked. Never shared, and you can leave any time.

— Nilay

or follow by RSSor on X

By subscribing you agree to the privacy note. One click to leave.

tip: paste the exact error text