PostgreSQL: password authentication failed, explained and fixed

FATAL: password authentication failed for user "app" is PostgreSQL's authentication rejection, and like its peers it does not reveal which part failed. PostgreSQL adds its own twist: whether a password is even the relevant credential, and how it is verified (SCRAM versus MD5), is decided per connection by the first matching line of pg_hba.conf, chosen by connection type, database, user, and source address. So the same correct password can succeed from one machine and fail from another, and the server's log (which records more detail than the client message, including the hba line number in many cases) is part of the diagnosis.

The checks, in order

  1. Verify the credential in the simplest client: psql -h <host> -U app -d <db> and type the password when prompted. Check for the usual silent corruptors: an old password in the application's environment or secrets, a trailing space, a .pgpass entry overriding what you think is being sent.
  2. Confirm the role exists and has a password: as a superuser, \du app and, if needed, set the password explicitly: ALTER ROLE app WITH LOGIN PASSWORD '...';. A role that does not exist produces this same client message, deliberately.
  3. Read the server's log for the failure: it names the database, user, source, and often the pg_hba.conf line applied. That line determines the method: if it says scram-sha-256 but the stored password verifier is an old MD5 secret and the client is older still, authentication fails despite the password being “right”; re-setting the password with the server's current password_encryption aligns the stored verifier.
  4. Reorder or repair the hba rule if it matched the wrong one: the first matching line wins, so a broad earlier rule (a host all all 0.0.0.0/0 md5 ahead of your specific rule, or a reject) governs. After editing, reload (SELECT pg_reload_conf();) rather than restarting.

The local-socket variant

  1. Local connections often use peer authentication on Linux packages: the operating-system user must equal the database role name. A failure there is not about passwords at all; either run the client as the matching OS user (the classic sudo -u postgres psql), or adjust the local rule in pg_hba.conf deliberately.

Common questions

Why does the same password work from the server but not from my app server? Different source addresses hit different pg_hba.conf lines with possibly different methods, and local peer rules do not apply over the network. The log's record of which line matched is the answer; the password was never the variable part.

I reset the password and it still fails with an old client, why? The stored verifier format and the client's capabilities must overlap with the hba method. Align all three: set password_encryption appropriately, re-set the password so it is stored in that format, and keep the hba method consistent.

Is this error a sign of an attack? A single occurrence from your own application is configuration. A stream of failures for many users from external addresses in the server log is password guessing, addressed at the network and hba level (restrict source ranges, require TLS), not by changing passwords alone.

Related errors

MySQL error 1045 (Access denied) · SQL Server error 18456 (Login failed) · ORA-01017: invalid username/password