Troubleshooting “user does not have a valid SCRAM secret” in PostgreSQL

Recently, I ran into an issue where, after updating a PostgreSQL user’s password with:

ALTER ROLE <user_name> WITH PASSWORD '<password>';

my Django application suddenly stopped connecting to the database and started throwing the following error even though credentials were correct:

 

OperationalError at /
connection to server at "<postgres_host>" (<ip-address>), port 5432 failed: 
FATAL:  password authentication failed for user "<postgres_user>"

I had to spend some time figuring out what was going wrong—and here's what I learned.

 I checked logs of my PG container and encountered the following:

FATAL:  password authentication failed for user "<postgres_user>"
DETAIL:  User "<postgres_user>" does not have a valid SCRAM secret.

The Root Cause: SCRAM-SHA-256 vs MD5 Passwords

PostgreSQL 13+ uses SCRAM‑SHA‑256 as the default password encryption mechanism, which is a more secure replacement for the older md5.

However, if you set or reset a password without explicitly configuring the encryption method, PostgreSQL might store it using the legacy md5 format—even though your pg_hba.conf is set to require SCRAM.

The Fix

To resolve this, you need to ensure the password is stored using SCRAM‑SHA‑256 format. Here’s how to do that properly:

  1. Connect to the PostgreSQL container or instance as a superuser (psql -U postgres).

  2. Run the following commands:

SET password_encryption = 'scram-sha-256';

-- Update the password again
ALTER ROLE <user_name> WITH PASSWORD '<password>';

Important: Don’t use ENCRYPTED or UNENCRYPTED explicitly. Just rely on SET password_encryption.

How to Verify

You can confirm that the password is now stored in SCRAM format:

SELECT rolname, rolpassword
FROM pg_authid
WHERE rolname = '<user_name>';

The rolpassword field should now start with SCRAM-SHA-256$.... If it still starts with md5, then the password is not compatible with your pg_hba.conf settings.

 

Final Thoughts

Whenever you're working with PostgreSQL and have authentication set to use scram-sha-256, make sure that any role's password is stored accordingly. Otherwise, clients—including Django apps—will fail to authenticate, even though the password might seem correct.

This fix doesn’t require restarting PostgreSQL or your containers—it works immediately after resetting the password properly.