PostgreSQL Error 3D000: Invalid Catalog Name
PostgreSQL error code 3D000 — invalid_catalog_name — occurs when a client attempts to connect to a database (catalog) that does not exist in the PostgreSQL cluster. In PostgreSQL terminology, a "catalog" refers to a database, so this error essentially means "the database you're trying to connect to cannot be found." It is one of the most common connection-related errors and typically surfaces during application startup, migrations, or environment configuration changes.
Top 3 Causes and Fixes
Cause 1: The Database Simply Does Not Exist
The most straightforward cause — the target database was never created, was accidentally dropped, or the name has a typo (e.g., mydb vs my_db).
Diagnosis:
-- List all databases in the cluster
SELECT datname FROM pg_catalog.pg_database ORDER BY datname;
-- Check for close matches (case-insensitive)
SELECT datname FROM pg_catalog.pg_database WHERE datname ILIKE '%mydb%';
Fix:
-- Create the missing database
CREATE DATABASE mydb
WITH
OWNER = myuser
ENCODING = 'UTF8'
TEMPLATE = template0;
-- Verify creation
SELECT datname, datcollate FROM pg_database WHERE datname = 'mydb';
Cause 2: Misconfigured Connection String or Environment Variable
Applications using DATABASE_URL or framework-specific config files (settings.py, application.properties, database.yml) often pass a wrong or empty database name — especially in containerized environments where environment variables fail to inject correctly.
Diagnosis:
-- After connecting, verify which database you're actually on
SELECT current_database(), current_user;
-- Check active connections and their target databases (requires superuser)
SELECT pid, datname, usename, application_name, client_addr
FROM pg_stat_activity
WHERE datname IS NOT NULL;
Fix:
Validate your connection string format and test it directly:
-- Test via psql (run in terminal)
-- psql "postgresql://myuser:mypassword@localhost:5432/mydb"
-- Pre-flight existence check before app startup
SELECT CASE
WHEN EXISTS (
SELECT 1 FROM pg_catalog.pg_database WHERE datname = 'mydb'
) THEN 'Database EXISTS'
ELSE 'Database MISSING'
END AS status;
Cause 3: Wrong Database Specified in CLI Tools or Scripts
Using psql \c, pg_dump -d, or pg_restore -d with an incorrect database name triggers this error. Automated scripts with broken variable substitution often pass an empty string as the database name.
Diagnosis and Fix:
-- In psql, always list databases before switching
\l
-- Switch to the correct database
\c mydb
-- Defensive check in SQL scripts
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM pg_catalog.pg_database WHERE datname = 'mydb'
) THEN
RAISE EXCEPTION 'Database "mydb" not found. Aborting.';
END IF;
END
$$;
For shell scripts, guard against empty variables:
-- Terminal guard example (bash):
-- DB_NAME="${DB_NAME:?ERROR: DB_NAME environment variable is not set}"
-- psql -U myuser -d "$DB_NAME" -c "SELECT current_database();"
Quick Prevention Tips
1. Add a pre-connection existence check to your startup logic.
Always query pg_catalog.pg_database to confirm the target database exists before your application boots or before running migration scripts. This turns a cryptic runtime crash into a clear, actionable error message.
-- Reusable existence check
SELECT COUNT(*) > 0 AS database_exists
FROM pg_catalog.pg_database
WHERE datname = current_setting('app.target_db', true);
2. Standardize and validate connection strings across environments.
Define a strict naming convention (e.g., appname_env → myapp_prod, myapp_staging) and enforce non-empty validation at the infrastructure level using secret managers (AWS Secrets Manager, HashiCorp Vault). Never allow a connection string with a blank or default placeholder database name to reach production.
Related Errors
| Code | Name | When it occurs |
|---|---|---|
28000 |
invalid_authorization_specification | Database exists but user access is denied |
08006 |
connection_failure | Cannot reach the PostgreSQL server at all |
42P04 |
duplicate_database | Trying to CREATE DATABASE with a name that already exists |
08001 |
sqlclient_unable_to_establish_sqlconnection | Client-side wrapper error that often masks 3D000
|
📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.
Top comments (0)