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 postgrespostgresql-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 bootjournalctl -u postgresql-19.service -b --no-pager# The most recent 100 messagesjournalctl -u postgresql-19.service -n 100 --no-pager# Detailed failure information, positioned at the newest entryjournalctl -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 use2026-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 use2026-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 sockets2026-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 server2026-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/datadrwx------ 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/dataf: /var/lib/pgsql/19/datadr-xr-xr-x root root /drwxr-xr-x root root vardrwxr-xr-x root root libdrwx------ postgres postgres pgsqldrwx------ root root 19drwx------ 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.pid954/var/lib/pgsql/19/data17910747335432/var/run/postgresqllocalhost184550130 0ready
The fields in postmaster.pid mean:
| Line | Value | Meaning |
|---|---|---|
| 1 | 954 | PID of the PostgreSQL main server process |
| 2 | /var/lib/pgsql/19/data | PostgreSQL data directory |
| 3 | 1791074733 | Server start time as Unix epoch seconds |
| 4 | 5432 | TCP port |
| 5 | /var/run/postgresql | Unix socket directory |
| 6 | localhost | Address PostgreSQL is listening on |
| 7 | 184550130 0 | Internal shared-memory key and segment ID |
| 8 | ready | PostgreSQL completed startup and is ready |
Convert the start timestamp:
[root@pg19 log]# date -d @1791074733Sun 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 -hdf -ifindmnt /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