Main Ecosystems
HomePython CorePandas ReferenceNumPy ScientificFastAPI & PydanticDjango Enterprise
More Ecosystems
Environment & SetupRequests & HTTPAsyncIO ConcurrencyObject-Oriented OOPPyTorch Deep LearningScikit-Learn MLFlask FrameworkWeb ScrapingDatabase & ORMDevOps & Docker

PostgreSQL / MySQL OperationalError: FATAL password authentication failed for user

Verified FixPython 3.10+Psycopg2 / PyMySQL / SQLAlchemy 2.0+Silo: database

Quick Fix / Solution Rapide

Verify database credentials, URL-encode special characters in connection strings (urllib.parse.quote_plus), and inspect pg_hba.conf authentication rules.

Root Cause Analysis

This error occurs when Python tries to connect to a relational database server (such as PostgreSQL or MySQL) using psycopg, pymysql, or SQLAlchemy, but the database server rejects the connection handshake due to invalid credentials, incorrect password encryption, or restrictive host access rules.

1. Unescaped Special Characters in Database URIs

In SQLAlchemy connection strings (e.g., postgresql://user:p@ss#word@localhost:5432/db), special characters like @, #, :, or / in passwords corrupt URI parsing. SQLAlchemy treats the @ inside the password as the boundary between credentials and host, sending a truncated password.

2. Environment Variable Configuration Drift

In containerized deployments, mismatch between .env file credentials and initialized database container volume credentials causes immediate authentication rejection.

3. PostgreSQL pg_hba.conf Authentication Methods (scram-sha-256 vs md5)

PostgreSQL 14+ enforces scram-sha-256 password hashing. Connecting with older client drivers or mismatched user password formats triggers fatal authentication failures.

4. Default Database and User Privileges

Attempting to authenticate as postgres or root from remote IP addresses when the database configuration only allows local socket connections.

Reproduction Code (MCVE)

Example: Bug Reproduction
# **Note de reproductibilité :** Dépendant de la configuration du serveur SQL distant.
class OperationalError(Exception):
    pass

raise OperationalError('FATAL: password authentication failed for user "app_user" (server rejected credentials)')

Solution 1: URL-Encode Special Characters in Connection Strings

Use urllib.parse.quote_plus to safely escape special characters in passwords when constructing database URLs.

Example: Recommended Solution
import urllib.parse

user = 'db_admin'
password = 'p@ss#word/2026!'
host = 'localhost'
port = 5432
database = 'production_db'

# Safely encode password
encoded_pwd = urllib.parse.quote_plus(password)
db_uri = f'postgresql+psycopg2://{user}:{encoded_pwd}@{host}:{port}/{database}'
print(f'Safely encoded database URI: {db_uri}')

Solution 2: Use Environment Variables with Structured Connection Dict

Pass credentials as a structured dictionary rather than a raw string to avoid URL parsing issues entirely.

Example: Alternative Solution
import os

connection_params = {
    'user': os.getenv('DB_USER', 'postgres'),
    'password': os.getenv('DB_PASSWORD', 'secret123'),
    'host': os.getenv('DB_HOST', '127.0.0.1'),
    'port': int(os.getenv('DB_PORT', 5432)),
    'dbname': os.getenv('DB_NAME', 'app_db')
}
print(f'Ready to connect to host: {connection_params["host"]} with user {connection_params["user"]}')

A common mistake is storing unquoted passwords containing % in .env files. Python dotenv parsers may interpolate % as variable expansions. Always wrap values in single quotes inside .env files. Edge cases occur with Docker Compose: changing POSTGRES_PASSWORD in docker-compose.yml does NOT update an existing PostgreSQL data volume in pgdata/. You must delete the volume (docker-compose down -v) to reinitialize credentials. Contrast this error with OperationalError: could not connect to server, which indicates network or port unreachability.