How to fix initdb: directory exists but is not empty in PostgreSQL

PostgreSQLINTERMEDIATEMEDIUMUpdated Dec 29, 2025ยท 310 views

The "initdb: directory exists but is not empty" error occurs when trying to initialize a new PostgreSQL database cluster while the data directory already contains files. This is a safety feature to prevent accidental data loss. The error can be fixed by using an empty directory, removing existing files, or specifying a different initialization directory.

Quick fix

Fixes initdb: directory exists but is not empty

# Check the directory contents
ls -la /var/lib/postgresql/data/

# On Docker, check volume mounts
docker inspect <container-name> | grep -A 5 "Mounts"
  1. Identify the data directory location
  2. Verify if the data directory contains valuable data
  3. Remove the data directory contents (if not needed)
  4. Use a different data directory path
postgresql โ€” error
# Check the directory contents
ls -la /var/lib/postgresql/data/
# On Docker, check volume mounts
docker inspect <container-name> | grep -A 5 "Mounts"
initdb: directory exists but is not empty

What this error means

When you run initdb to create a new PostgreSQL database cluster, it requires an empty directory as the data directory. If the target directory already contains files (from a previous incomplete initialization, old database files, or leftover configuration files), initdb refuses to proceed to prevent accidentally overwriting or corrupting existing data. This is an intentional safety mechanism built into PostgreSQL.

Typical symptoms

  • initdb command fails with "directory exists but is not empty" message
  • PostgreSQL initialization fails when creating a new cluster
  • Error occurs when mounting a volume in Docker with existing files
  • Previous initdb attempts left behind orphaned configuration files
  • Data directory shows files like pg_hba.conf or postgresql.conf from failed initialization

Common causes

  1. The target data directory contains leftover files from a previous failed initdb attempt
  2. Mounting a non-empty Docker volume to the PostgreSQL data directory
  3. Files were accidentally created in the data directory before running initdb
  4. Attempting to re-initialize an existing PostgreSQL cluster
  5. The directory exists from a previous installation that was not properly cleaned up
  6. Using the same directory for multiple PostgreSQL versions without clearing it first

How to fix "initdb: directory exists but is not empty"

1Identify the data directory location

First, determine which directory initdb is trying to use. The error message will specify the path, typically something like /var/lib/postgresql/data or /var/lib/pgsql/data. In Docker, this is usually mapped as a volume.

bash
# Check the directory contents
ls -la /var/lib/postgresql/data/

# On Docker, check volume mounts
docker inspect <container-name> | grep -A 5 "Mounts"
2Verify if the data directory contains valuable data

Before removing or clearing the directory, check if it contains important data:

bash
# Look for PostgreSQL version marker
cat /var/lib/postgresql/data/PG_VERSION

# Check for WAL files or backups
ls -la /var/lib/postgresql/data/pg_wal/

# List all files to understand what's present
find /var/lib/postgresql/data -type f

If PG_VERSION exists and you need the data, back it up before proceeding.

3Remove the data directory contents (if not needed)

If the directory contains only leftover files from a failed initialization and no valuable data:

bash
# Option 1: Remove the entire directory
sudo rm -rf /var/lib/postgresql/data

# Option 2: Empty just the contents while keeping the directory
sudo rm -rf /var/lib/postgresql/data/*

# Verify the directory is now empty
ls -la /var/lib/postgresql/data/

Then run initdb again with the empty directory.

4Use a different data directory path

As an alternative, run initdb with a different directory path instead of removing files:

bash
# Initialize PostgreSQL in a different directory
initdb -D /var/lib/postgresql/data_new

# If you need to use the old path later, rename after initialization
sudo mv /var/lib/postgresql/data_old /var/lib/postgresql/data_backup
sudo mv /var/lib/postgresql/data_new /var/lib/postgresql/data
5For Docker: Handle volume mounting correctly

If this error occurs in Docker, ensure the volume is properly initialized:

bash
# Option 1: Use Docker named volumes (recommended)
docker run -v postgres_data:/var/lib/postgresql/data postgres:latest

# Option 2: Clean the host directory before mounting
sudo rm -rf /host/postgres/data/*
docker run -v /host/postgres/data:/var/lib/postgresql/data postgres:latest

# Option 3: Use -v with a fresh directory
docker run -v /fresh/empty/directory:/var/lib/postgresql/data postgres:latest
6Verify successful initialization

Once you've cleared or changed the directory, initdb should succeed:

bash
# Run initdb
initdb -D /var/lib/postgresql/data

# You should see output like:
# "The files belonging to this database system will be owned by user \"postgres\"..."
# "Success. You can now start the database server using..."

# Verify the initialized cluster
ls -la /var/lib/postgresql/data/
cat /var/lib/postgresql/data/PG_VERSION

# Start PostgreSQL
pg_ctl -D /var/lib/postgresql/data -l logfile start

Advanced notes

In production environments, always back up data before removing directories. If you're migrating between PostgreSQL versions, use pg_dump to export data from the old version, then initialize a new cluster and import the dump. When using Docker Compose, prefer named volumes over bind mounts to avoid permission and initialization issues. If initdb leaves behind partially initialized files (like pg_hba.conf and postgresql.conf without PG_VERSION), it's safe to remove them. The error message itself provides the solution: "either remove or empty the directory ... or run initdb with an argument other than the directory". Consider setting filesystem permissions to prevent accidental file creation: chmod 700 /var/lib/postgresql/data after initialization.

Frequently asked questions

What does "initdb: directory exists but is not empty" mean?
When you run initdb to create a new PostgreSQL database cluster, it requires an empty directory as the data directory. If the target directory already contains files (from a previous incomplete initialization, old database files, or leftover configuration files), initdb refuses to proceed to prevent accidentally overwriting or corrupting existing data. This is an intentional safety mechanism built into PostgreSQL.
How do I fix "initdb: directory exists but is not empty"?
The "initdb: directory exists but is not empty" error occurs when trying to initialize a new PostgreSQL database cluster while the data directory already contains files. This is a safety feature to prevent accidental data loss. The error can be fixed by using an empty directory, removing existing files, or specifying a different initialization directory.
What causes "initdb: directory exists but is not empty"?
The target data directory contains leftover files from a previous failed initdb attempt Mounting a non-empty Docker volume to the PostgreSQL data directory Files were accidentally created in the data directory before running initdb
Is the "initdb: directory exists but is not empty" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading