Posted on:January 15, 2026 at 12:00 AM

Fixing PostgreSQL Stale postmaster.pid Lock File

Fixing PostgreSQL Stale postmaster.pid Lock File

Fixing PostgreSQL Stale postmaster.pid Lock File

The Problem

PostgreSQL service shows an error status in Homebrew:

 brew services list
Name              Status   User  File
postgresql@17     error  1 user ~/Library/LaunchAgents/[email protected]

The Investigation

Checking the Logs

The PostgreSQL log revealed the issue:

 tail -50 /opt/homebrew/var/log/[email protected]

2026-01-15 10:57:27.984 PST [49027] FATAL:  lock file "postmaster.pid" already exists
2026-01-15 10:57:27.984 PST [49027] HINT:  Is another postmaster (PID 732) running in data directory "/opt/homebrew/var/postgresql@17"?

PostgreSQL was failing to start because a postmaster.pid lock file already existed, claiming PID 732 was using it.

Checking the Lock File

 cat /opt/homebrew/var/postgresql@17/postmaster.pid

732
/opt/homebrew/var/postgresql@17
1764184024
5432
/tmp
localhost
 21922676     65536
stopping

The lock file contained:

  • PID 732 - the process ID that supposedly owns the lock
  • Port 5432 - the PostgreSQL port
  • Status: “stopping” - PostgreSQL was mid-shutdown when something went wrong

Checking if PID 732 is Actually PostgreSQL

 ps aux | grep -E "^.* 732 "

user  732  0.0  0.1 435406032  59968  ??  S  Tue10AM  0:11.34 /System/Library/PrivateFrameworks/IMCore.framework/imagent.app/Contents/MacOS/imagent

PID 732 is macOS’s iMessage daemon (imagent), not PostgreSQL!

Root Cause

  1. PostgreSQL was running with PID 732
  2. The system was shut down or PostgreSQL crashed while in “stopping” state
  3. The postmaster.pid lock file was not cleaned up
  4. After reboot, macOS assigned PID 732 to a different process (imagent)
  5. PostgreSQL refuses to start because the lock file claims PID 732 is still using the data directory
  6. PostgreSQL doesn’t verify if PID 732 is actually a postgres process

The Solution

Remove the stale lock file and restart PostgreSQL:

rm /opt/homebrew/var/postgresql@17/postmaster.pid
brew services restart postgresql@17

Understanding postmaster.pid

The postmaster.pid file serves several purposes:

  1. Prevents multiple instances - Ensures only one PostgreSQL server uses a data directory
  2. Stores connection info - Contains port number and socket directory for clients
  3. Enables clean shutdown - Used by pg_ctl stop to find the running server

Lock File Format

<PID>
<Data Directory>
<Postmaster Start Timestamp>
<Port>
<Unix Socket Directory>
<Listen Addresses>
<Shared Memory Key> <Shared Memory Size>
<Status>

When Lock Files Become Stale

  • System crash or power loss
  • kill -9 on the postgres process
  • PostgreSQL crash during shutdown
  • Container/VM termination without graceful shutdown

Prevention

  1. Always shut down PostgreSQL gracefully:

    brew services stop postgresql@17
  2. Before system shutdown, ensure PostgreSQL is stopped

  3. If PostgreSQL crashes, check for and remove stale lock files before restarting

Safety Note

Before removing postmaster.pid, always verify that no PostgreSQL process is actually running:

# Check for any postgres processes
pgrep -l postgres

# Or more thoroughly
ps aux | grep postgres | grep -v grep

Only remove the lock file if no PostgreSQL processes are found. Removing it while PostgreSQL is running can cause data corruption.

Related Posts