What it means
PostgreSQL stores each table and index as files, and grows them a block at a time. To add rows it asked the operating system for more space, and the file system said it had none:
ERROR: could not extend file "pg_tblspc/54582/PG_18_202506291/24576/54583": No space left on device
HINT: Check free disk space.
The statement fails and its changes are rolled back. The path says where: base/<database oid>/<file> for the default location, pg_tblspc/<tablespace oid>/… for another tablespace.
Queries that need temporary files fail the same way, with
could not write to file "…/pgsql_tmp/pgsql_tmp59.0": No space left on device.
When the disk is full, more than inserts break. In our test VACUUM and TRUNCATE failed too,
because both need a little space to work. If the volume holding WAL (pg_wal) fills up, the
server can’t continue at all: the documentation warns it may shut down with a PANIC.
Common causes
- The data really outgrew the disk: a table or index that kept growing, or bloat from rows that were updated or deleted but never vacuumed away.
- WAL kept for a replication slot whose consumer stopped (a replica that’s down, a logical replication or CDC tool that was removed): PostgreSQL keeps every WAL file the slot hasn’t confirmed.
- Temporary files from a query sorting or hashing far more data than expected.
- Something outside PostgreSQL: server logs, backups or dumps written to the same disk.
- A small volume: a Docker volume, a cloud disk without autoscaling, or a tablespace on a small mount.
How to fix it
Find what’s using the space
On the server: df -h for each volume, then du -sh $PGDATA/* to compare base, pg_wal and the
rest. In SQL:
SELECT datname, pg_size_pretty(pg_database_size(datname)) FROM pg_database ORDER BY 2 DESC;
SELECT relname, pg_size_pretty(pg_total_relation_size(oid)) AS size
FROM pg_class WHERE relkind IN ('r', 'm')
ORDER BY pg_total_relation_size(oid) DESC LIMIT 10;
Check replication slots
SELECT slot_name, active, wal_status,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained
FROM pg_replication_slots;
An inactive slot holding gigabytes is a common cause of a full pg_wal. If its consumer is gone for
good, drop it (SELECT pg_drop_replication_slot('<name>');) and PostgreSQL removes the WAL at the
next checkpoint. Setting max_slot_wal_keep_size stops a slot keeping unlimited WAL in the future.
Free space safely
- Remove files outside PostgreSQL first: old logs, dumps, backups.
DROP TABLEreleases a table’s files at once. In our test it worked on the full tablespace whenVACUUMandTRUNCATEdidn’t.- Grow the volume, if you can; most cloud disks can be enlarged while running.
- Never delete files in
pg_wal(orpg_xact) by hand: the database needs them to recover, and removing them can corrupt it.
Stop it happening again
Monitor free space, set temp_file_limit so one query can’t fill the disk with temporary files, and
vacuum regularly so bloat doesn’t accumulate. Reclaiming bloat with
VACUUM FULL needs room for a full copy of the table while it
runs, so it can’t help when the disk is already full.
Reproduce it
We didn’t fill the disk of a shared test server. In a throwaway PostgreSQL 18.6 container, we
mounted an 8 MB tmpfs at /mnt/tiny, made it a tablespace, and filled a table in it:
CREATE TABLESPACE tiny LOCATION '/mnt/tiny/ts';
CREATE TABLE logs (id bigint, line text) TABLESPACE tiny;
INSERT INTO logs SELECT g, repeat('x', 200) FROM generate_series(1, 100000) g;
ERROR: could not extend file "pg_tblspc/54582/PG_18_202506291/24576/54583": No space left on device
HINT: Check free disk space.
With \set VERBOSITY verbose the code was 53100. The table had 0 rows (the insert was rolled
back) but its file still took 8160 kB, the whole volume. On the full tablespace, VACUUM logs failed
with could not extend file "…/54583_vm": No space left on device (it couldn’t create the visibility
map), and TRUNCATE logs failed the same way for its new file. DROP TABLE logs worked, and df
showed the volume empty again. With temp_tablespaces = tiny and a small work_mem, a large sort
failed with:
ERROR: could not write to file "pg_tblspc/54582/PG_18_202506291/pgsql_tmp/pgsql_tmp59.0": No space left on device
In Inlet
When a statement fails, Inlet shows the server’s error with PostgreSQL’s hint, and What this error
means opens this page. Inlet’s backups use the bundled pg_dump; write them to a different disk
from the database’s, so a backup can’t be the thing that fills it.