This error occurs when you attempt to connect to a PostgreSQL database that doesn't exist on the server. It commonly happens when psql tries to connect to a database with the same name as your OS user account, or when you specify an incorrect database name in your connection string.
The "FATAL: database 'dbname' does not exist" error indicates that PostgreSQL received a valid connection request with valid credentials, but the target database is not present on the server. This is different from authentication failures. PostgreSQL has a unique behavior: when you run `psql` without specifying a database name with the `-d` flag, it attempts to connect to a database with the same name as the current operating system user. If this database hasn't been created, you'll get this error. For example: - If your OS user is `john` and you run `psql` without arguments, PostgreSQL tries to connect to a database named `john` - If you specify a database with `-d myapp` but the database doesn't exist, you get this error - This differs from MySQL/MariaDB which uses a different security model The SQLSTATE error code is 3D000 (database_name_not_found).
Connect to PostgreSQL using the default postgres database and list all databases:
# Connect to the postgres database (default, always exists)
psql -h localhost -U postgres -d postgresAt the postgres=# prompt, list all databases:
\l
-- or
SELECT datname FROM pg_database WHERE datistemplate = false;This shows all non-template databases on your server. Check if your target database is listed.
To exit psql:
\qIf the database doesn't exist, create it using the createdb command or SQL:
Method 1: Using createdb (recommended for scripts)
# Basic creation
createdb -h localhost -U postgres myapp_db
# With additional options (specific owner, encoding)
createdb -h localhost -U postgres -O myapp_user -E UTF8 myapp_dbMethod 2: Using CREATE DATABASE SQL
Connect to the postgres database and run:
psql -h localhost -U postgres -d postgresThen at the prompt:
CREATE DATABASE myapp_db;
-- Or with specific owner and encoding
CREATE DATABASE myapp_db
OWNER myapp_user
ENCODING 'UTF8'
LOCALE 'en_US.UTF-8';
-- Verify it was created
\lImportant parameters:
- OWNER: Which PostgreSQL role (user) owns the database. Defaults to the connecting user
- ENCODING: Character set. Use 'UTF8' for modern applications
- LOCALE / LC_COLLATE / LC_CTYPE: Language and collation settings (important for sorting and string operations)
Note: CREATE DATABASE cannot be run inside a transaction block. If you get an error about being in a transaction, first run ROLLBACK;
Ensure your application is connecting to the correct database name:
Check your connection string format:
PostgreSQL connection string patterns:
# URL format (libpq)
postgresql://user:password@localhost:5432/database_name
# Connection parameters (key=value)
host=localhost dbname=database_name user=postgres password=yourpasswordCommon mistakes to avoid:
1. Wrong database name:
// ✗ WRONG - database 'app' doesn't exist
const pool = new Pool({ database: 'app' });
// ✓ CORRECT - use the actual database name
const pool = new Pool({ database: 'myapp_db' });2. Using OS username instead of database name:
# ✗ WRONG - assumes database named 'john' exists
psql
# ✓ CORRECT - explicitly specify database
psql -d myapp_db3. Missing database name in connection URL:
# ✗ WRONG - no database specified
psql postgresql://postgres@localhost
# ✓ CORRECT - includes database name
psql postgresql://postgres@localhost/myapp_dbCheck environment variables:
# See what your app is trying to use
echo $DATABASE_URL
echo $PGDATABASE
echo $PGHOST
echo $PGUSERIf you're using the default behavior of psql (connecting to a database matching your OS username), create that database:
# If your OS user is 'john', create a database named 'john'
sudo -u postgres createdb john
# Or manually as the postgres user
sudo -u postgres psql -c "CREATE DATABASE john;"Now psql will work without arguments:
psql # Connects to database 'john'For multi-user development environments:
Instead of creating per-user databases, create a shared development database and use it explicitly:
# Create a shared development database
sudo -u postgres createdb dev_database
# Users connect explicitly
psql -d dev_databaseDouble-check all connection parameters:
# Test connection with explicit parameters
psql \
--host localhost \
--port 5432 \
--username postgres \
--dbname myapp_db \
--command "SELECT version();"If this works, your database exists and is accessible. If not:
Check which PostgreSQL instance is running:
# Find running PostgreSQL processes
ps aux | grep postgres
# Find the data directory (important for multi-instance setups)
# On Linux
grep data_directory /etc/postgresql/*/main/postgresql.conf
# On macOS with Homebrew
/usr/local/var/postgres/Verify the server is listening on the expected port and host:
# Check what ports PostgreSQL is listening on
ss -tlnp | grep postgres
# or
netstat -tlnp | grep postgres
# Test connectivity to the host/port
nc -zv localhost 5432
telnet localhost 5432When using PostgreSQL in Docker, the database must be created. The official postgres image has initialization scripts:
Using POSTGRES_DB environment variable:
FROM postgres:16
ENV POSTGRES_USER=postgres
ENV POSTGRES_PASSWORD=secret
ENV POSTGRES_DB=myapp_db # This database will be created automaticallyOr with docker-compose:
services:
postgres:
image: postgres:16
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp_db # Created automatically
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres_data:For custom initialization scripts:
Place SQL or shell scripts in /docker-entrypoint-initdb.d/ and they'll run once when the container starts:
FROM postgres:16
COPY init-schema.sql /docker-entrypoint-initdb.d/Important: Initialization scripts only run when the volume is empty. If you want to reinitialize:
# Remove the volume
docker volume rm myapp_postgres_data
# Recreate the container
docker-compose up -d postgresPostgreSQL vs MySQL connection model:
PostgreSQL uses a different security model than MySQL/MariaDB:
- MySQL defaults to a 'mysql' database that always exists
- PostgreSQL defaults to connecting to a database named after the OS user
- This is a common migration issue for developers switching from MySQL
Database ownership and permissions:
When you create a database with a specific owner, only that owner and superusers can connect without special privileges:
-- Create database owned by specific user
CREATE DATABASE myapp_db OWNER myapp_user;
-- Grant connection privilege to another user
GRANT CONNECT ON DATABASE myapp_db TO other_user;
-- View database ownership
SELECT datname, pg_catalog.pg_get_userbyid(datdba) as owner
FROM pg_database;Replication and multi-instance setups:
In high-availability setups with replication:
- The database exists on the primary server
- It's replicated to standby servers
- Connection strings must point to the correct server
- Use connection pooling to handle failover (e.g., pg_partman, Stolon)
Template databases:
PostgreSQL has special 'template' databases used to clone new databases:
- template0: Never modified, safe to use as base
- template1: Can be customized, used by default
If you delete a database, you're not deleting template files - you must explicitly recreate it.
Common automation scenarios:
For Kubernetes deployments, initialize databases with init containers:
initContainers:
- name: db-init
image: postgres:16
command:
- sh
- -c
- |
until pg_isready -h postgres -p 5432; do
sleep 2
done
psql -h postgres -U postgres -c "CREATE DATABASE IF NOT EXISTS myapp_db;"Connection pooling considerations:
Tools like PgBouncer or pg_partman need the database to exist:
- Configure the database in pooler config before starting
- Test pooler connection separately from app connection
- Pooler errors can obscure the real "database not found" issue
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL
ERROR 42501: must be owner of table
How to fix "must be owner of table" in PostgreSQL
trigger cannot change partition destination
How to fix "Trigger cannot change partition destination" in PostgreSQL
SSL error: certificate does not match host name
SSL error: certificate does not match host name in PostgreSQL
No SSL connection
No SSL connection to PostgreSQL