Postgres "FATAL: password authentication failed for user" in CI
Postgres accepted the connection and rejected the credentials. The password supplied by the client does not match the role, so authentication fails. This is deterministic - retrying with the same wrong password fails identically.
What this error means
psql or a migration tool fails with "FATAL: password authentication failed for user", naming the role. It fails the same way every run because the credential is wrong, not because of timing.
psql: error: connection to server at "postgres" (172.18.0.2), port 5432 failed:
FATAL: password authentication failed for user "app"Common causes
Password mismatch between service and client
The POSTGRES_PASSWORD set on the service container differs from the password in DATABASE_URL or PGPASSWORD used to connect.
Secret not injected
A ${{ secrets.DB_PASSWORD }} reference is empty (wrong secret name, missing in the environment), so the client sends no/empty password.
Role created with a different password
An init script created the role with one password while the connection string uses another.
How to fix it
Align the service password and the connection string
Use the same value for the service env and the client URL.
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${{ secrets.DB_PASSWORD }}
env:
DATABASE_URL: postgresql://app:${{ secrets.DB_PASSWORD }}@localhost:5432/appVerify the secret is actually set
- Assert the password is non-empty without printing it:
test -n "$PGPASSWORD". - Confirm the secret name matches exactly - names are case-sensitive.
- Recreate the role/password if an init script set a different value.
How to prevent it
- Source the database password from one secret used by both the service and the client.
- Add an early assertion that the password env var is present.
- Retrying will not fix an authentication failure - it is deterministic; correct the credential.