Skip to main content

Python Psycog2: How to Resolve "psycopg2 OperationalError" in Python

When connecting to a PostgreSQL database using Python's psycopg2 library, you may encounter psycopg2.OperationalError, a broad exception that indicates something went wrong with the database connection or operation. This error can be triggered by incorrect credentials, network problems, a stopped database server, or configuration issues. In this guide, we'll cover the most common causes of this error, show what each error message looks like, and provide clear solutions for each scenario.

What Is psycopg2.OperationalError?

psycopg2.OperationalError is an exception class in the psycopg2 library (Python's most popular PostgreSQL adapter) that covers a range of connection and operational failures. Unlike programming errors, operational errors are typically caused by external factors: wrong credentials, unreachable servers, or misconfigured databases.

The error usually includes a descriptive message that tells you exactly what went wrong. Learning to read these messages is the key to fixing the issue quickly.

Common Causes and Solutions

1. Incorrect Database Credentials

The most frequent cause is providing wrong values for the database name, username, password, host, or port.

❌ Wrong: Incorrect database name

import psycopg2

conn = psycopg2.connect(
dbname="my_databse", # Typo: should be "my_database"
user="postgres",
password="mypassword",
host="localhost",
port="5432"
)

Output:

psycopg2.OperationalError: FATAL:  database "my_databse" does not exist

❌ Wrong: Incorrect password

conn = psycopg2.connect(
dbname="my_database",
user="postgres",
password="wrong_password",
host="localhost",
port="5432"
)

Output:

psycopg2.OperationalError: FATAL:  password authentication failed for user "postgres"

✅ Correct: Use verified credentials

import psycopg2

try:
conn = psycopg2.connect(
dbname="my_database",
user="postgres",
password="correct_password",
host="localhost",
port="5432"
)
print("Connected successfully!")
conn.close()
except psycopg2.OperationalError as e:
print(f"Connection failed: {e}")

Output:

Connected successfully!
How to Verify Your Credentials

Test your credentials directly with PostgreSQL's command-line tool before debugging Python code:

psql -h localhost -p 5432 -U postgres -d my_database

If this fails, the issue is with your credentials or PostgreSQL configuration, not with psycopg2.

2. PostgreSQL Server Is Not Running

If the PostgreSQL service isn't running, psycopg2 can't establish a connection.

Error output

psycopg2.OperationalError: could not connect to server: Connection refused
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP/IP connections on port 5432?

Fix: Start the PostgreSQL service

# Linux (systemd)
sudo systemctl start postgresql
sudo systemctl status postgresql

# macOS (Homebrew)
brew services start postgresql

# Windows
net start postgresql-x64-15 # Version number may vary

Verify the server is running:

pg_isready -h localhost -p 5432

Expected output

localhost:5432 - accepting connections

3. Wrong Host or Port

If your PostgreSQL server is running on a different host or port than what you've specified, the connection will fail.

Error output (wrong host)

psycopg2.OperationalError: could not translate host name "wrong-host" to address: Name or service not known

Error output (wrong port)

psycopg2.OperationalError: could not connect to server: Connection refused
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP/IP connections on port 5433?

Fix: Find the correct host and port:

# Check which port PostgreSQL is listening on
sudo ss -tlnp | grep postgres

# Or check the PostgreSQL config file
cat /etc/postgresql/15/main/postgresql.conf | grep port

Then update your connection parameters:

conn = psycopg2.connect(
dbname="my_database",
user="postgres",
password="mypassword",
host="localhost", # Or the actual server IP
port="5432" # Match the actual port
)

4. PostgreSQL Not Accepting TCP/IP Connections

By default, some PostgreSQL installations only accept local Unix socket connections and reject TCP/IP connections.

Error output

psycopg2.OperationalError: could not connect to server: Connection refused

Fix: Configure PostgreSQL to accept TCP/IP connections

Step 1: Edit postgresql.conf to listen on all addresses:

# Find the config file
sudo -u postgres psql -c "SHOW config_file;"

# Edit it
sudo nano /etc/postgresql/15/main/postgresql.conf

Change:

#listen_addresses = 'localhost'

To:

listen_addresses = '*'    # Or 'localhost' for local connections only

Step 2: Edit pg_hba.conf to allow password authentication:

sudo nano /etc/postgresql/15/main/pg_hba.conf

Add or modify:

# TYPE  DATABASE  USER  ADDRESS        METHOD
host all all 127.0.0.1/32 md5
host all all 0.0.0.0/0 md5 # For remote connections

Step 3: Restart PostgreSQL:

sudo systemctl restart postgresql
caution

Allowing connections from 0.0.0.0/0 opens your database to all IP addresses. In production, restrict this to specific IP ranges and always use strong passwords or certificate-based authentication.

5. Database Does Not Exist

If you specify a database name that hasn't been created, you'll get an error.

Error output

psycopg2.OperationalError: FATAL:  database "myapp_db" does not exist

Fix: Create the database

# Using psql
sudo -u postgres psql -c "CREATE DATABASE myapp_db;"

# Or interactively
sudo -u postgres createdb myapp_db

Then connect:

conn = psycopg2.connect(
dbname="myapp_db",
user="postgres",
password="mypassword",
host="localhost",
port="5432"
)
print("Connected!")

6. SSL Connection Required

Some PostgreSQL servers (especially cloud-hosted ones like AWS RDS, Heroku, or Supabase) require SSL connections.

Error output

psycopg2.OperationalError: FATAL:  no pg_hba.conf entry for host "x.x.x.x", user "postgres", database "mydb", SSL off

Fix: Enable SSL in the connection

import psycopg2

conn = psycopg2.connect(
dbname="my_database",
user="postgres",
password="mypassword",
host="your-cloud-host.amazonaws.com",
port="5432",
sslmode="require" # Enable SSL
)
print("Connected with SSL!")

Common sslmode values:

ModeDescription
disableNo SSL
allowTry non-SSL first, then SSL
preferTry SSL first, then non-SSL (default)
requireMust use SSL (no certificate verification)
verify-caMust use SSL with CA certificate verification
verify-fullMust use SSL with full certificate verification

7. Too Many Connections

PostgreSQL has a maximum connection limit (default is usually 100). Exceeding it causes an error.

Error output

psycopg2.OperationalError: FATAL:  too many connections for role "postgres"

Fix: Close connections properly and use connection pooling:

import psycopg2
from psycopg2 import pool

# Create a connection pool instead of individual connections
connection_pool = pool.SimpleConnectionPool(
minconn=1,
maxconn=10,
dbname="my_database",
user="postgres",
password="mypassword",
host="localhost",
port="5432"
)

# Get a connection from the pool
conn = connection_pool.getconn()

try:
cursor = conn.cursor()
cursor.execute("SELECT version();")
print(cursor.fetchone())
cursor.close()
finally:
# Return the connection to the pool (don't close it)
connection_pool.putconn(conn)

# When completely done
connection_pool.closeall()
tip

Always close connections when you're done. Use try/finally blocks or context managers to ensure connections aren't leaked:

conn = psycopg2.connect(...)
try:
# Do work
pass
finally:
conn.close()

Robust Connection Template

Here's a production-ready connection pattern with proper error handling:

import psycopg2
import sys
import os

def get_db_connection():
"""Establish a connection to PostgreSQL with error handling."""
try:
conn = psycopg2.connect(
dbname=os.environ.get("DB_NAME", "my_database"),
user=os.environ.get("DB_USER", "postgres"),
password=os.environ.get("DB_PASSWORD", ""),
host=os.environ.get("DB_HOST", "localhost"),
port=os.environ.get("DB_PORT", "5432"),
connect_timeout=5, # Timeout after 5 seconds
)
print("✅ Connected to PostgreSQL successfully.")
return conn
except psycopg2.OperationalError as e:
error_message = str(e).strip()

if "does not exist" in error_message:
print(f"❌ Database not found: {error_message}")
elif "password authentication failed" in error_message:
print(f"❌ Authentication failed: {error_message}")
elif "Connection refused" in error_message:
print("❌ Connection refused. Is PostgreSQL running?")
elif "could not translate host name" in error_message:
print(f"❌ Invalid host: {error_message}")
else:
print(f"❌ Connection error: {error_message}")

sys.exit(1)


# Usage
conn = get_db_connection()
try:
cursor = conn.cursor()
cursor.execute("SELECT version();")
print(f"PostgreSQL version: {cursor.fetchone()[0]}")
cursor.close()
finally:
conn.close()
print("Connection closed.")

Output (successful connection):

✅ Connected to PostgreSQL successfully.
PostgreSQL version: PostgreSQL 15.4 on x86_64-pc-linux-gnu...
Connection closed.

Diagnostic Checklist

When you encounter psycopg2.OperationalError, work through these checks:

#CheckCommand
1Read the full error messageIt tells you exactly what's wrong
2Is PostgreSQL running?pg_isready -h localhost -p 5432
3Can you connect via psql?psql -h localhost -U postgres -d mydb
4Is the port correct?ss -tlnp | grep postgres
5Is TCP/IP enabled?Check postgresql.conflisten_addresses
6Is authentication configured?Check pg_hba.conf
7Does the database exist?psql -l to list databases
8Is SSL required?Add sslmode="require" to connection
9Are connections exhausted?Check with SELECT count(*) FROM pg_stat_activity;

Conclusion

The psycopg2.OperationalError is a catch-all exception for connection and operational failures with PostgreSQL.

The error message itself is your best diagnostic tool: it tells you whether the problem is wrong credentials, a stopped server, a network issue, a missing database, or an SSL requirement.

Always start by reading the full error message, verify your credentials with psql directly, check that PostgreSQL is running and accepting connections, and use proper error handling with try/except blocks in your code.

For production applications, use connection pooling and environment variables for credentials to build robust, maintainable database connections.