- SQLSTATE
- 28P01
- Condition name
invalid_password- Product
- PostgreSQL
- Versions
- PostgreSQL 13 to 18
- Last reviewed
- 24 October 2026
On this page
What it means
SQLSTATE 28P01 means the server reached the password check for this login and the check failed: a wrong, missing or expired password, or a password stored in a form the pg_hba.conf method cannot use.
When a client connects, PostgreSQL picks the first matching line in pg_hba.conf. If that line uses a password method (scram-sha-256, md5 or password), the server asks for a password and checks it against the role's stored password in pg_authid. If the check fails, the login ends with FATAL: password authentication failed for user "..." and SQLSTATE 28P01 (invalid_password). As the documentation puts it, the server is willing to talk to you, but not until you pass the authentication method in pg_hba.conf.
The client is deliberately told very little. The same message appears when the password is wrong, when the role has no password (then password authentication always fails), when its VALID UNTIL time has passed, and even when the role does not exist, so that an attacker cannot use the message to discover role names. The documentation's advice: the server log contains more information than the client gets, so read it when the reason is unclear. psql and other libpq programs print the server message after their own connection to server ... failed: prefix.
Common causes
- The password in the connection string, environment variable (PGPASSWORD), .pgpass file or application secret is wrong or out of date after a rotation.
- The role has no password set (common for roles created without PASSWORD, or the postgres role on a fresh install that used peer authentication locally).
- The role's VALID UNTIL time has passed, so its password is no longer accepted.
- The password is stored as an MD5 hash but the matching pg_hba.conf line requires scram-sha-256, which an MD5-hashed password cannot satisfy.
- The client connects as a different role than intended (a typo, a default user name, or a pooler that rewrites the user), or the role does not exist at all.
Diagnose it
Read-only These queries only read the system catalogs (pg_catalog, information_schema) and statistics views such as pg_stat_activity and pg_locks. They do not change data, roles or settings, so they are safe to run first.
Read the server log entry for the failed login
The client sees only "password authentication failed". The server log for the same attempt records the real reason (for example that the role does not exist, has no password, has an expired password or that the password did not match) and which pg_hba.conf line matched the connection. On managed services, use the provider's log viewer.
Does the role exist, can it log in, and has its password expired?
Run as an administrator over a connection that works (for example a local one).
SELECT rolname, rolcanlogin, rolvaliduntil,
rolvaliduntil < now() AS password_expired
FROM pg_roles
WHERE rolname = 'andym'; No row: the role does not exist. rolcanlogin = false: the role cannot log in at all (a different message, SQLSTATE 28000). password_expired = true: the VALID UNTIL time has passed.
Is a password stored, and in which format?
pg_authid is readable only by superusers. This shows whether a password exists and whether it is a SCRAM hash, without showing the hash.
SELECT rolname,
rolpassword IS NOT NULL AS has_password,
rolpassword LIKE 'SCRAM-SHA-256$%' AS is_scram
FROM pg_authid
WHERE rolname = 'andym';
SELECT current_setting('password_encryption') AS password_encryption; has_password = false means password authentication will always fail for this role. is_scram = false with a password present means an MD5 hash, which works only with the md5 or password methods.
Which pg_hba.conf rule applies to this connection?
pg_hba_file_rules shows the file as currently written on disk (superusers only), in order. The first line that matches the connection type, database, user and client address is the one used.
SELECT rule_number, line_number, type, database, user_name,
address, netmask, auth_method, error
FROM pg_hba_file_rules
ORDER BY rule_number; The auth_method of the first matching line. A non-null error column means that line has a syntax problem.
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Correct the password the client sends
Client or network sideCheck every place the client can take a password from: the connection string or DSN, the PGPASSWORD environment variable, the .pgpass file (on Windows %APPDATA%\postgresql\pgpass.conf) and the application's secret store. A .pgpass line is hostname:port:database:username:password and the first matching line wins, so an older line above the correct one is a common surprise.
Set a new password
Changes permissionsIn psql, the \password command prompts for the new password and sends it already hashed, so the clear text does not end up in the server log or the shell history. ALTER ROLE ... PASSWORD does the same job from any client, but the literal password may be logged. With password_encryption set to scram-sha-256 (the default), the new password is stored as a SCRAM hash, which also fixes an old MD5 hash.
Caution: Update every application and .pgpass file that uses this role at the same time, or they will start failing with this error.
-- in psql, connected as a superuser or a role with CREATEROLE:
\password andym
-- or, from any client:
ALTER ROLE andym PASSWORD 'a-long-random-password';
Extend an expired password
Changes permissionsIf VALID UNTIL has passed, set a new expiry time (or infinity), ideally together with a new password.
ALTER ROLE andym VALID UNTIL '2027-06-30';
Create the role if it is missing
Changes permissionsIf the server log says the role does not exist, create it with LOGIN and a password, then grant only the privileges it needs.
CREATE ROLE andym LOGIN PASSWORD 'a-long-random-password';
GRANT CONNECT ON DATABASE testdb TO andym;
Examples
Logging in over TCP with a wrong password
Shown as documented in the PostgreSQL documentation (Client Authentication, Authentication Problems). This example needs a running PostgreSQL server (a login over TCP that matches a password rule in pg_hba.conf), which PGlite does not provide, so it was not reproduced here.
-- From a shell on the client machine:
-- psql "host=server.joe.com port=5432 dbname=testdb user=andym"
-- Password for user andym: (a wrong password is typed)
FATAL: password authentication failed for user "andym"
A role whose password has expired
The message is the documented one (Client Authentication, Authentication Problems): the client is not told that the password expired, only the server log says so. This example needs a running PostgreSQL server (a password login after the VALID UNTIL time), which PGlite does not provide, so it was not reproduced here.
-- As an administrator:
CREATE ROLE andym LOGIN PASSWORD 'secret' VALID UNTIL '2026-01-01';
-- Later, from the client:
-- psql "host=server.joe.com dbname=testdb user=andym" (correct password)
FATAL: password authentication failed for user "andym"
How to prevent it
Keep each application's password in one secret store that every instance reads, rotate it by setting the new password and updating all consumers together, and avoid hard-coded passwords and stray .pgpass lines. Use scram-sha-256 in pg_hba.conf and password_encryption, and set any MD5-hashed passwords again so they are stored as SCRAM.
If you use VALID UNTIL, monitor rolvaliduntil so passwords are renewed before they expire. Watch the server log for repeated failures from one address; they can point to a misconfigured client or to password guessing.
Common questions
How do I fix "password authentication failed for user" in PostgreSQL?
Check the server log for the real reason, confirm the role exists and has a valid, unexpired password, then either correct the password the client sends (connection string, PGPASSWORD, .pgpass) or set a new one with \password in psql.
Why does PostgreSQL say the password failed when the user does not exist?
With password methods the server goes through the motions of password authentication even for unknown roles, so the client gets the same message and cannot discover which role names exist. The server log states that the role does not exist.
I just installed PostgreSQL: what is the postgres password?
There may not be one. Linux packages such as the Debian and Ubuntu ones set up local peer authentication for the postgres role, so it logs in without a password from the postgres operating system account. Connect that way (sudo -u postgres psql) and set a password with \password postgres before using password logins. The Windows installer asks for a password during setup.
Learn more on CodeWithSQL
Official documentation
Last technically reviewed 24 October 2026; examples and diagnostics run on PostgreSQL 18.6 documentation; SQL-level parts in PGlite 0.5.11. SQL-level examples were run in PGlite (PostgreSQL compiled to WebAssembly); examples that need a running server are shown as documented in the PostgreSQL documentation.