Incident brief
Invalid catalog name
A connection attempt named a database that doesn't exist. PostgreSQL rejected the connection before it was ever established.
In 10 seconds
- What
- Invalid catalog name
- What triggers it
- Try to connect to a database name that has never been created.
- The fix
- Connect using the correct, existing database name.
- Proof
- Reproduced on PostgreSQL 16.14 → Connecting to a database name that had never been created was rejected with SQLSTATE 3D000. The correct database name, tried right afterward, connected normally.
The fix
What to do right now
The immediate, application-level response to this error.
- Connect using the correct, existing database name.
- If the database genuinely should exist, create it first with CREATE DATABASE — but see the counterexample for why you can't do that inline as part of the same failed attempt.
- Double-check for typos and case — PostgreSQL folds unquoted database names to lowercase, so case mismatches trigger this same SQLSTATE even for a database that does exist.
-- reconnect using the correct, existing database name
SELECT 1 AS connected_successfully;Diagnose
See it live on the server
Run these against the affected instance to confirm the diagnosis before you act.
Standard triage — not specific to this error
These are canonical PostgreSQL system-catalog queries, shown as SQL to run. No sample output is attached because this is general triage, not a captured lab transcript.This SQLSTATE does not have an error-specific live snapshot yet. These are the canonical system-catalog queries you run against the affected server to see the problem in real time — standard triage, not a reproduced transcript.
What is running right now
Active backends, how long each has been running, and what it is waiting on.
SELECT pid,
state,
wait_event_type,
wait_event,
now() - query_start AS running_for,
left(query, 80) AS query
FROM pg_stat_activity
WHERE state <> 'idle'
AND pid <> pg_backend_pid()
ORDER BY running_for DESC NULLS LAST;Who is blocking whom
Turn raw blocking PIDs into the actual queries on both sides of the wait.
SELECT blocked.pid AS blocked_pid,
blocked.query AS blocked_query,
blocking.pid AS blocking_pid,
blocking.query AS blocking_query
FROM pg_stat_activity AS blocked
JOIN LATERAL unnest(pg_blocking_pids(blocked.pid)) AS b(pid) ON true
JOIN pg_stat_activity AS blocking ON blocking.pid = b.pid
WHERE cardinality(pg_blocking_pids(blocked.pid)) > 0;Locks that are still waiting
Every lock a backend has requested but not yet been granted.
SELECT l.pid,
l.locktype,
l.mode,
l.granted,
COALESCE(c.relname, l.transactionid::text) AS object
FROM pg_locks l
LEFT JOIN pg_class c ON c.oid = l.relation
WHERE NOT l.granted
ORDER BY l.pid;Why it happens
What PostgreSQL is telling you
The mechanism behind the error, grounded in the official manual — not paraphrased.
PostgreSQL 16 Documentation — Creating a Database
In order to create a database, the PostgreSQL server must be up and running... Databases are created with the SQL command CREATE DATABASE.Read the full section on postgresql.org →
Nonexistent database name
analytics_replica has never been created in this cluster. PostgreSQL rejects the connection outright at startup — it never gets far enough to run a query.Correct database name, right afterward
The identical connection attempt, with only the database name corrected, succeeded immediately — confirming the earlier failure was specifically about the database name.Reproduce & verify
A real reproduction at the connection stage
A literal transcript of SQL run against a live PostgreSQL instance in an isolated lab — the commands below are exactly what was executed.
- 1Try to connect to a database name that has never been created.
- 2SQLSTATE 3D000 is reported as a FATAL connection error; no session is ever established.
One client, tried twice: first against a nonexistent database name, then against the correct one.
-- No schema needed: this reproduces at the connection stage, before any query runs.
SELECT 'no schema required' AS setup_note;psql -U postgres -d analytics_replica-- reconnect using the correct, existing database name
SELECT 1 AS connected_successfully;What PostgreSQL actually returned
setup_note
--------------------
no schema required
(1 row)psql: error: connection to server on socket "..." failed: FATAL: database "analytics_replica" does not exist connected_successfully
-------------------------
1
(1 row)A database created with a quoted, mixed-case name behaves differently from an ordinary lowercase one. This was tested directly: creating "BillingDB" (quoted, mixed case), then connecting with the plain lowercase form of that same name.
Create a database with a quoted, mixed-case name, then try to connect using the unquoted lowercase form of that same name.
Without this
Above: guessing at a database name that was never created at all fails with SQLSTATE 3D000.
With this, tested
Below: a database that does exist can still trigger the identical SQLSTATE 3D000 if the case doesn't match.
What Pro unlocks here
- The exact prevention SQL — copy-paste ready
- Raw psql output captured from the Docker lab
- A senior-DBA action list to take it further
- Live monitoring queries to catch it in production
- The deeper audit: fix-that-fails counterexample, GUC before/after, server-log evidence
Related & next steps
Follow the thread
Everything this error touches — jump straight to the sibling error, term, runbook, or parameter.
Related errors
Verification
- Last verified
- 2026-07-16 (Docker lab, PostgreSQL 16.14)
- Reviewed by
- Verified against PostgreSQL 16.14 in an isolated lab environment
- Audit status
- reviewed