How to fix initdb: directory exists but is not empty in PostgreSQL
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"- Identify the data directory location
- Verify if the data directory contains valuable data
- Remove the data directory contents (if not needed)
- Use a different data directory path
# Check the directory contentsls -la /var/lib/postgresql/data/# On Docker, check volume mountsdocker 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
- 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
- Attempting to re-initialize an existing PostgreSQL cluster
- The directory exists from a previous installation that was not properly cleaned up
- Using the same directory for multiple PostgreSQL versions without clearing it first
How to fix "initdb: directory exists but is not empty"
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.
# Check the directory contents
ls -la /var/lib/postgresql/data/
# On Docker, check volume mounts
docker inspect <container-name> | grep -A 5 "Mounts"Before removing or clearing the directory, check if it contains important data:
# 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 fIf PG_VERSION exists and you need the data, back it up before proceeding.
If the directory contains only leftover files from a failed initialization and no valuable data:
# 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.
As an alternative, run initdb with a different directory path instead of removing files:
# 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/dataIf this error occurs in Docker, ensure the volume is properly initialized:
# 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:latestOnce you've cleared or changed the directory, initdb should succeed:
# 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 startAdvanced 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
- ๐PostgreSQL Official Documentation
- ๐PostgreSQL Error Codes Appendix(Official Docs)
- ๐PostgreSQL initdb Documentation(Official Docs)
- ๐