When working with PostgreSQL, one of the first problems we may encounter is a PostgreSQL server that fails to start. This article explains how to diagnose PostgreSQL startup failures by identifying the systemd service, finding its startup command and data directory, and running the same command in the foreground to expose the startup error.

1. Find the startup command and data directory

First, identify the PostgreSQL systemd service. List the currently loaded services with:

# systemctl list-units --type=service | grep -i postgres
postgresql-19.service loaded active running PostgreSQL 19 database server

After identifying the service name, use journalctl to inspect the output collected by systemd:

journalctl -u postgresql-19.service --no-pager

You can narrow the output with these useful filters:

# Messages from the current boot
journalctl -u postgresql-19.service -b --no-pager
# The most recent 100 messages
journalctl -u postgresql-19.service -n 100 --no-pager
# Detailed failure information, positioned at the newest entry
journalctl -xeu postgresql-19.service --no-pager

Inspect the service unit to find its startup command:

# systemctl cat postgresql-19.service
...
Environment=PGDATA=/var/lib/pgsql/19/data/
...
ExecStartPre=/usr/pgsql-19/bin/postgresql-19-check-db-dir ${PGDATA}
ExecStart=/usr/pgsql-19/bin/postmaster -D ${PGDATA}

postmaster is a symbolic link to postgres, retained for historical compatibility. The ExecStart entry shows the command used to start the PostgreSQL server:

# sudo -u postgres /usr/pgsql-19/bin/postgres -D /var/lib/pgsql/19/data/

Running the command directly prints the startup error in the terminal. Stop the foreground process with Ctrl-C.

2. Major Causes of Startup Failures

Use the foreground command to investigate the common causes of PostgreSQL startup failures.

Invalid configuration

An invalid value or syntax error in postgresql.conf can prevent PostgreSQL from starting. The following example shows the resulting error:

[root@pg19 data]# sudo -u postgres /usr/pgsql-19/bin/postgres -D /var/lib/pgsql/19/data/
2026-10-04 02:15:18.344 UTC [13894] LOG: 0 is outside the valid range for parameter "max_connections" (1 .. 262143)
2026-10-04 02:15:18.344 UTC [13894] FATAL: configuration file "/var/lib/pgsql/19/data/postgresql.conf" contains errors

The LOG line identifies the invalid value. The following FATAL line reports that PostgreSQL rejected the configuration file and stopped startup.

The immediate cause is that max_connections cannot be 0. However, there is an important trap: the value you see may not be the value PostgreSQL uses. A parameter can appear multiple times in postgresql.conf or in an included configuration file. PostgreSQL processes assignments in order, and the last assignment takes effect. 

We can check the value of the max_connections parameter with the following command without starting the PostgreSQL service:

sudo -u postgres /usr/pgsql-19/bin/postgres \
-D /var/lib/pgsql/19/data -C max_connections

Port Already in Use

If another process is using port 5432, PostgreSQL reports the address conflict in its startup log. A typical error looks like this:

2026-10-04 10:15:16.639 UTC [14222] LOG: could not bind IPv6 address "::1": Address already in use
2026-10-04 10:15:16.639 UTC [14222] HINT: Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
2026-10-04 10:15:16.639 UTC [14222] LOG: could not bind IPv4 address "127.0.0.1": Address already in use
2026-10-04 10:15:16.639 UTC [14222] HINT: Is another postmaster already running on port 5432? If not, wait a few seconds and retry.
2026-10-04 10:15:16.639 UTC [14222] WARNING: could not create listen socket for "localhost"
2026-10-04 10:15:16.639 UTC [14222] FATAL: could not create any TCP/IP sockets
2026-10-04 10:15:16.640 UTC [14222] LOG: database system is shut down

Use the following command to identify the process using port 5432:

[root@pg15 ~]# ss -ltnp | grep ':5432'
LISTEN 0 128 127.0.0.1:5432 *:* users:(("some-service",pid=14216,fd=3))
LISTEN 0 128 ::1:5432 :::* users:(("some-service",pid=14216,fd=4))

Wrong or Incompatible Data Directory

PostgreSQL cannot start if the service points to the wrong data directory:


[root@pg15 ~]# sudo -u postgres /usr/pgsql-15/bin/postgres  -D /var/b/pgsql/15/data_wrong
postgres: could not access directory "/var/lib/pgsql/15/data_wrong": No such file or directory
Run initdb or pg_basebackup to initialize a PostgreSQL data directory.


Even when the data directory path is correct, the cluster may have been initialized by a different PostgreSQL major version. PG_VERSION records the major version that initialized the cluster. In this case, the data directory reported version 16 while the server executable was PostgreSQL 19:

[root@pg19 data]# sudo -u postgres /usr/pgsql-19/bin/postgres -D /var/lib/pgsql/19/data/
2026-10-04 02:19:11.636 UTC [13909] FATAL: database files are incompatible with server
2026-10-04 02:19:11.636 UTC [13909] DETAIL: The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 19.0.

PostgreSQL reads PG_VERSION before opening the database files. PostgreSQL 19 cannot use a data directory initialized by PostgreSQL 16. Do not edit PG_VERSION manually. A major-version change requires the supported pg_upgrade or dump-and-restore procedure.

Permission and Ownership Errors

The data directory and its files must be accessible to the postgres account. The following example shows what happens when PostgreSQL cannot access the data directory:


[root@pg19 data]# sudo -u postgres /usr/pgsql-19/bin/postgres -D /var/lib/pgsql/19/data/
LOG:  could not change directory to "/var/lib/pgsql/19/data": Permission denied
postgres: could not access directory "/var/lib/pgsql/19/data": Permission denied



Test whether the postgres account can access the data directory with:


[root@pg19 data]# sudo -u postgres touch /var/lib/pgsql/19/data/testfile
touch: cannot create "/var/lib/pgsql/19/data/testfile": Permission denied


We check the ownership of the directory:

[root@pg15 ~]# ls -ld /var/lib/pgsql/15/data
drwx------ 20 postgres postgres 4096 10月 4 10:23 /var/lib/pgsql/15/data

The data directory itself is owned by postgres, so use namei to check the ownership and permissions of every parent directory in the path:

[root@pg19 data]# namei -l /var/lib/pgsql/19/data
f: /var/lib/pgsql/19/data
dr-xr-xr-x root root /
drwxr-xr-x root root var
drwxr-xr-x root root lib
drwx------ postgres postgres pgsql
drwx------ root root 19
drwx------ postgres postgres data

The root:root ownership and drwx------ mode on the 19 directory prevent postgres from traversing the path. Restore its ownership before starting PostgreSQL:

chown postgres:postgres /var/lib/pgsql/19

After ownership is restored, PostgreSQL can access the data directory and continue starting normally.

Stale postmaster.pid File

PostgreSQL uses postmaster.pid as a lock and status file. It prevents two PostgreSQL servers from using the same data directory. The following is an example:

[root@pg19 data]# cat /var/lib/pgsql/19/data/postmaster.pid
954
/var/lib/pgsql/19/data
1791074733
5432
/var/run/postgresql
localhost
184550130 0
ready

The fields in postmaster.pid mean:

LineValueMeaning
1954PID of the PostgreSQL main server process
2/var/lib/pgsql/19/dataPostgreSQL data directory
31791074733Server start time as Unix epoch seconds
45432TCP port
5/var/run/postgresqlUnix socket directory
6localhostAddress PostgreSQL is listening on
7184550130 0Internal shared-memory key and segment ID
8readyPostgreSQL completed startup and is ready

Convert the start timestamp:

[root@pg19 log]# date -d @1791074733
Sun Oct 4 00:45:33 UTC 2026

After an unclean shutdown, a stale PID file can prevent startup. Do not delete it blindly. First verify that no PostgreSQL process is using the data directory. If the file is confirmed to be stale, remove it and retry the startup.

Disk Space, Inode, or Filesystem Problems

PostgreSQL may fail to start or complete recovery when the data or WAL filesystem is full or read-only. Check the filesystem with:

df -h
df -i
findmnt /var/lib/pgsql/19/data

Key Takeaway

To troubleshoot a PostgreSQL startup failure, identify the systemd service, find its startup command and data directory, and run the command in the foreground as the postgres user. The resulting error, together with the PostgreSQL and systemd logs, usually identifies the cause: an invalid configuration, a port conflict, an incorrect data directory, insufficient permissions, a stale PID file, or a filesystem problem.

Leave a Reply

I’m Yuan

Welcome to the blog of a database performance maven. Feel free to contact me to share and discuss database knowledge.

My Oracle Book

My 26 Oracle Certifications

A screenshot from certview.oracle.com

My MySQL Book

MySQL 8.0 Operations and Optimization

Let’s connect