Troubleshooting
Shared Memory Troubleshooting
A PostgreSQL
No space left on devicemessage can mean exhausted operating system IPC capacity rather than a full disk; identify the failed system call before changing configuration or removing resources.
Identify the Failure
Read the complete PostgreSQL diagnostic, including DETAIL and HINT:
| Diagnostic | Resource | First check |
|---|---|---|
could not create shared memory segment with shmget(...) |
System V shared memory | Segment count and stale postmasters |
could not create semaphores with semget(...) |
System V semaphores | Semaphore limits and server concurrency |
could not resize shared memory segment "/PostgreSQL..." |
Dynamic shared memory | The configured dynamic implementation and its backing capacity |
could not extend file or another named filesystem path |
Disk storage | Free blocks and inodes on that filesystem |
The automatic recovery described below applies only to the first case on
macOS. Settings such as shared_buffers, max_connections, and
max_locks_per_transaction do not free a System V segment ID left by a dead
server.
Automatic macOS Recovery
PostgreSQL records its System V shared-memory key and segment ID in
postmaster.pid. When that file names a dead postmaster, local-postgres can
remove the recorded segment before continuing:
| Lifecycle path | Recovery point |
|---|---|
startPostgres and startPostgresDataDir |
Before starting an existing data directory |
Their returned stop() operations |
After the managed postmaster exits |
stopPostgresDataDir |
When the recorded or expected postmaster is already dead or exits during shutdown |
local-postgres/tmp |
Through the same core lifecycle, including its detached cleanup worker |
There is no option to enable. On macOS, recovery runs automatically and invokes
/usr/bin/ipcs and /usr/bin/ipcrm directly without a shell.
Before removing anything, local-postgres requires all of these facts to
agree:
postmaster.pidbelongs to the current user and records the requested data directory- the recorded postmaster PID no longer exists
- the kernel entry has the recorded key, segment ID, and creator PID
- the kernel entry's owner and creator are the current user
- no process is attached to the segment
- an
expectedPid, when supplied, matches the recorded postmaster generation
Any missing field, conflicting value, attached process, unexpected command output, or command failure preserves the segment. The lifecycle then continues; a later startup may report PostgreSQL's original error. When a logger is configured, successful recovery produces a message like:
[postgres] Removed stale shared memory segment 19529730 for .postgres.
Know the Recovery Boundary
Automatic recovery is intentionally not a user-wide IPC sweep. It cannot remove a segment when:
- its data directory or
postmaster.pidwas already deleted postmaster.pidis malformed or does not contain the segment identity- an unrelated stale segment exhausted the system-wide limit
- a new cluster fails inside
initdb, before it has durable postmaster identity forlocal-postgresto verify - another process remains attached
- the host is Linux, Windows, or another non-macOS platform
These limits prevent one cluster lifecycle from deleting IPC resources owned by another PostgreSQL installation or application.
Inspect macOS System V Capacity
Check the system-wide segment limit and list the current segments:
sysctl kern.sysv.shmmni
ipcs -m -p
ipcs -m -o
Join the two ipcs views by segment ID. CPID is the creator PID and NATTCH
is the number of attached processes. Compare a cluster's recorded PID, key, and
segment ID without modifying anything:
sed -n -e '1p' -e '7p' .postgres/postmaster.pid
ps -p "$(head -n 1 .postgres/postmaster.pid)" -o pid=,command=
An absent creator PID and NATTCH=0 are necessary evidence of a stale segment,
but they do not by themselves prove that the segment belongs to this package.
Retain the data-directory and postmaster.pid match as the ownership boundary.
Recover When Automatic Cleanup Cannot
Prefer these remedies in order:
Restart the same cluster through
startPostgres. An intactpostmaster.pidlets the package apply its exact-match recovery.Reboot the development machine when the original data directories are gone or the remaining segments cannot be attributed safely. Rebooting clears stale System V IPC state.
Remove one exact segment manually only after verifying its current-user ownership, dead creator PID, zero attachments, and PostgreSQL provenance:
ipcrm -m <SHMID>Removal cannot be undone, although a genuinely stale shared-memory segment contains no database files. Never remove an attached segment or run a broad user-wide IPC cleanup while PostgreSQL or another IPC-using application is active.
Increase the operating system's
SHMMNIlimit when the machine intentionally runs more concurrent PostgreSQL servers than the current limit permits. This is an administrator-level, machine-wide change and may require a reboot depending on the macOS version.
Diagnose Dynamic Shared-Memory Resize Failures
An error containing could not resize shared memory segment "/PostgreSQL..."
does not use the stale System V recovery above. Check PostgreSQL's selected
implementation:
SHOW dynamic_shared_memory_type;
On Linux, a posix implementation is commonly backed by /dev/shm; inspect it
even when PostgreSQL runs directly rather than in Docker:
df -h /dev/shm
For development clusters where POSIX shared memory is unavailable or too constrained, callers can initialize a new cluster with memory-mapped files in its data directory:
await startPostgres({
dataDir: '.postgres',
config: {
dynamic_shared_memory_type: 'mmap',
},
})
config applies only when a cluster is first initialized. PostgreSQL generally
discourages mmap for production because modified pages may cause additional
disk I/O. See PostgreSQL's documentation for: