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 privilege to bypass row security
How to fix "insufficient privilege to bypass row security" in PostgreSQL
HV004: fdw_invalid_data_type
How to fix "HV004: fdw_invalid_data_type" in PostgreSQL
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