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.
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.
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 startIn 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.
ERROR: syntax error at end of input
Syntax error at end of input in PostgreSQL
Bind message supplies N parameters but prepared statement requires M
Bind message supplies N parameters but prepared statement requires M in PostgreSQL
Multidimensional arrays must have sub-arrays with matching dimensions
Multidimensional arrays must have sub-arrays with matching dimensions
ERROR: value too long for type character varying
Value too long for type character varying
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL