What happened
Your server crashed โ power outage, OOM kill, kernel panic, whatever โ and now PostgreSQL refuses to start. The error you're seeing:
FATAL: lock file "/var/run/postgresql/14-main.pid" already exists
HINT: Is another postmaster (PID 12345) running in data directory "/var/lib/postgresql/14/main"?
PostgreSQL writes its PID into postmaster.pid at startup. On a clean shutdown, it deletes that file. Crash? No chance. The stale file lingers, and the next startup sees it and refuses to boot โ it assumes another instance is already running.
The fix takes under two minutes. But first, confirm PostgreSQL is actually not running before you touch anything.
Step 1: Confirm nothing is actually running
Before deleting anything, rule out the possibility that a PostgreSQL process is genuinely alive:
# Check if postgres processes exist
ps aux | grep postgres
# Check if anyone is listening on the default port
sudo ss -tlnp | grep 5432
An active postgres process or something bound to port 5432 means stop โ you may have two instances colliding. Investigate with pg_lsclusters (Debian/Ubuntu) before doing anything else.
Nothing shows up? The PID file is definitely stale. Proceed.
Step 2: Check what's in the PID file
cat /var/run/postgresql/14-main.pid
The first line is the PID PostgreSQL recorded when it last started. Cross-check it:
ps -p 12345
No such process โ or a completely unrelated program that happened to inherit that PID โ means the file is stale and safe to remove.
Step 3: Remove the stale lock file
sudo rm /var/run/postgresql/14-main.pid
There's a second lock file inside the data directory itself. Check for it:
sudo ls -la /var/lib/postgresql/14/main/postmaster.pid
Found it? Remove that one too:
sudo rm /var/lib/postgresql/14/main/postmaster.pid
/var/run/postgresql/ holds the init system's copy; the data directory holds PostgreSQL's own internal lock. After a crash, both go stale.
Step 4: Start PostgreSQL
sudo systemctl start postgresql@14-main
# Or, if you're using the generic service name:
sudo systemctl start postgresql
Watch the logs immediately:
sudo journalctl -u postgresql@14-main -n 50 --no-pager
You're looking for database system is ready to accept connections. See it? You're done.
Step 5: Verify the fix
# Confirm the service is active
sudo systemctl status postgresql@14-main
# Connect and run a quick sanity check
sudo -u postgres psql -c "SELECT version();"
Check that the new PID file was written correctly:
cat /var/run/postgresql/14-main.pid
It should contain the PID of the freshly started process. Confirm it matches a running postgres:
ps aux | grep postgres | head -5
If PostgreSQL still won't start after removing the PID file
A stale PID file isn't always the only casualty of a crash. Pull the PostgreSQL log for clues:
sudo tail -100 /var/log/postgresql/postgresql-14-main.log
Common follow-on issues:
- Shared memory not released โ older PostgreSQL versions sometimes left shared memory segments behind. List them with
ipcs -m, then remove orphaned entries:ipcrm -m <shmid>(e.g.,ipcrm -m 327681). - Data directory needs recovery โ seeing
database system was not properly shut downin the log is normal after a crash. PostgreSQL will replay its WAL and recover automatically. Let it run โ most databases finish in under a minute. - Permissions changed โ verify the data directory is still owned by
postgres:ls -la /var/lib/postgresql/14/. Wrong owner? Fix it withsudo chown -R postgres:postgres /var/lib/postgresql/14/main.
Quick reference: where are the PID files?
- Ubuntu/Debian PG 14:
/var/run/postgresql/14-main.pid - RHEL/CentOS/Fedora:
/var/run/postgresql/postmaster.pid - Data directory lock:
/var/lib/postgresql/14/main/postmaster.pid(or wherever yourPGDATApoints) - Custom install: check the
PGDATAenv variable or runpg_lsclusters
Why this keeps happening (and how to reduce it)
The root cause is always an unclean shutdown. A few things worth addressing:
- UPS for database servers โ skipped most often in dev and staging. That's exactly where this error shows up.
- systemd
TimeoutStopSecโ PostgreSQL getting killed mid-reboot because it takes too long to flush? Raise the stop timeout. AddTimeoutStopSec=120to the service unit viasudo systemctl edit postgresql@14-main. - OOM killer โ if Postgres is being OOM-killed, that's a separate problem entirely. Run
dmesg | grep -i oomafter a crash to confirm. - VM snapshots โ reverting a running VM to a snapshot leaves stale PID files every time. Shut down cleanly before snapshotting, or expect to run through this fix after each revert.
The fix is low-risk. PostgreSQL's WAL-based crash recovery handles data integrity on its own. Removing the PID file just clears a bookkeeping artifact the crash left behind.

