How to fix FATAL: database "dbname" does not exist in PostgreSQL

PostgreSQLBEGINNERHIGHUpdated Dec 26, 2025· 178 views

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.

Quick fix

Fixes 3D000

# Connect to the postgres database (default, always exists)
psql -h localhost -U postgres -d postgres
  1. Verify the database exists on the server
  2. Create the missing database
  3. Fix connection strings and environment variables
  4. For development: Create a user-specific database
postgresql — error
# Connect to the postgres database (default, always exists)
psql -h localhost -U postgres -d postgres
FATAL: database "dbname" does not exist

What this error means

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).

Typical symptoms

  • psql connection fails with 'FATAL: database' error
  • Application connection strings fail when database name doesn't exist
  • Running psql without arguments fails for non-postgres users
  • Migration tools (Flyway, Liquibase) fail with database not found
  • Connection poolers (PgBouncer) report database doesn't exist
  • Node.js, Python, or other client libraries report connection failure

Common causes

  1. Database was never created on the PostgreSQL server
  2. psql defaults to connecting to a database named after your OS user (which doesn't exist)
  3. Database name in connection string is spelled incorrectly
  4. Database was deleted or dropped accidentally
  5. Connecting to the wrong PostgreSQL instance or host
  6. Database exists in a different PostgreSQL cluster than the one you're connecting to
  7. Using legacy connection parameters from an old database that no longer exists

How to fix "FATAL: database "dbname" does not exist"

1Verify the database exists on the server

Connect to PostgreSQL using the default postgres database and list all databases:

bash
# Connect to the postgres database (default, always exists)
psql -h localhost -U postgres -d postgres

At the postgres=# prompt, list all databases:

sql
\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:

sql
\q
2Create the missing database

If the database doesn't exist, create it using the createdb command or SQL:

Method 1: Using createdb (recommended for scripts)

bash
# 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_db

Method 2: Using CREATE DATABASE SQL

Connect to the postgres database and run:

bash
psql -h localhost -U postgres -d postgres

Then at the prompt:

sql
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
\l

Important 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;

3Fix connection strings and environment variables

Ensure your application is connecting to the correct database name:

Check your connection string format:

PostgreSQL connection string patterns:

bash
# URL format (libpq)
postgresql://user:password@localhost:5432/database_name

# Connection parameters (key=value)
host=localhost dbname=database_name user=postgres password=yourpassword

Common mistakes to avoid:

1. Wrong database name:

javascript
// ✗ 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:

bash
# ✗ WRONG - assumes database named 'john' exists
   psql

   # ✓ CORRECT - explicitly specify database
   psql -d myapp_db

3. Missing database name in connection URL:

bash
# ✗ WRONG - no database specified
   psql postgresql://postgres@localhost

   # ✓ CORRECT - includes database name
   psql postgresql://postgres@localhost/myapp_db

Check environment variables:

bash
# See what your app is trying to use
echo $DATABASE_URL
echo $PGDATABASE
echo $PGHOST
echo $PGUSER
4For development: Create a user-specific database

If you're using the default behavior of psql (connecting to a database matching your OS username), create that database:

bash
# 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:

bash
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:

bash
# Create a shared development database
sudo -u postgres createdb dev_database

# Users connect explicitly
psql -d dev_database
5Verify connection parameters and credentials

Double-check all connection parameters:

bash
# 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:

bash
# 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:

bash
# 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 5432
6For Docker: Ensure database is created during initialization

When using PostgreSQL in Docker, the database must be created. The official postgres image has initialization scripts:

Using POSTGRES_DB environment variable:

dockerfile
FROM postgres:16

ENV POSTGRES_USER=postgres
ENV POSTGRES_PASSWORD=secret
ENV POSTGRES_DB=myapp_db  # This database will be created automatically

Or with docker-compose:

yaml
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:

dockerfile
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:

bash
# Remove the volume
docker volume rm myapp_postgres_data

# Recreate the container
docker-compose up -d postgres

Advanced notes

PostgreSQL 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:

sql
-- 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:

yaml
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

Frequently asked questions

What does "3D000" mean?
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.
How do I fix "3D000"?
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.
What causes "3D000"?
Database was never created on the PostgreSQL server psql defaults to connecting to a database named after your OS user (which doesn't exist) Database name in connection string is spelled incorrectly
Is the "3D000" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading