← Blog · Reliability Engineering · September 14, 2026 · 6 min read · By Operate Technical Content Team

No Space Left on Device Is Not a Disk Problem Eight Times Out of Ten: A Production Decision Procedure for ENOSPC

ENOSPC has at least eight causes and most are not a full disk. An ordered production procedure across Linux, Docker, Kubernetes, Postgres and CI.

No Space Left on Device Is Not a Disk Problem Eight Times Out of Ten: A Production Decision Procedure for ENOSPC

No Space Left on Device Is Not a Disk Problem Eight Times Out of Ten: A Production Decision Procedure for ENOSPC

TL;DR: The Linux kernel returns ENOSPC (Errno 28) for at least eight structurally unrelated conditions, many of which have nothing to do with available disk bytes. To diagnose a failure when df looks healthy, you must systematically check for inode exhaustion, deleted-but-open file handles, and inotify watch limits.

Errno 28 is one number for eight different problems

In production environments, receiving a no space left on device error is rarely as simple as a full hard drive. The kernel returns ENOSPC (Error No Space) for a variety of resource exhaustion scenarios. If you have ever run df -h, seen 40% availability, and still watched a write operation fail, you are experiencing the structural ambiguity of Errno 28.

The problem with most troubleshooting guides is that they treat no space left on device as a single issue with one fix: delete files. In a complex stack involving Docker, Kubernetes, and Postgres, that advice is often irrelevant. You need a decision procedure that rules out branches of possibility until the root cause is isolated.

Check the path that failed, not the root filesystem

The most common wasted step in an incident is checking the wrong filesystem. A system might have 500GB free on /, but the process is trying to write to a 64MB tmpfs partition or a specific container volume that is at its limit.

The Rule: Run findmnt -T on the exact failing path provided in your logs.

# Identify which mount the failing path belongs to
findmnt -T /var/lib/data/my-app/logs

# Check both block and inode usage for THAT specific mount
df -hT /var/lib/data/my-app/logs
df -ih /var/lib/data/my-app/logs

What this rules out: The "Wrong Filesystem" error. If the usage is low on the specific mount returned by findmnt, you have ruled out simple block exhaustion and must look deeper.

The eight conditions, each with its tell and what it rules out

Follow this order. Each step is designed to eliminate a specific architectural cause of linux no space left on device errors.

1. Blocks exhausted

2. Inodes exhausted

3. Deleted but still open

4. Reserved blocks

5. Quotas

6. Container and orchestrator limits

7. Filesystem-specific allocation (Btrfs/XFS/LVM)

8. Not about disk at all: inotify watch exhaustion

Key Takeaway: If df, df -i, and lsof +L1 all come back clean, stop looking at storage and check whether the failing syscall was inotify_add_watch.

The fast triage block

Paste this into your terminal to capture the state of a failing mount immediately:

TARGET_PATH="/path/to/failure"
echo "--- Mount Info ---"
findmnt -T $TARGET_PATH
echo "--- Block & Inode Usage ---"
df -hT $TARGET_PATH && df -ih $TARGET_PATH
echo "--- Deleted but Open Files ---"
lsof -nP +L1 | head -n 20
echo "--- Inotify Limits ---"
sysctl fs.inotify.max_user_watches
Result Likely Condition
df Use% = 100% Block Exhaustion
df -i IUse% = 100% Inode Exhaustion
lsof shows (deleted) Open File Handles
Syscall is inotify_add_watch Inotify Limit

Where this shows up outside a plain Linux host

In modern production, ENOSPC often originates in the managed service layer:

Blast radius: what ENOSPC breaks that you will not notice

The danger of a no space left on device error isn't just the failed write; it's the state inconsistency it leaves behind. A database that cannot write its WAL may shut down. A service might half-write a configuration file, leading to a CrashLoopBackOff on restart.

Because these investigations require checking multiple layers—from the kernel syscall to the Kubernetes event log to the Postgres internal state—they are difficult to perform manually during an active incident. The reason this procedure is worth writing down is that a human doing it at 3am has to hold eight branches in their head while the incident is still running. This is exactly the kind of investigation Operate automates. Operate watches production, finds the root cause with evidence across the stack (like identifying an inotify exhaustion while others are looking at df), and drafts the fix as a PR.

Common pitfalls

Sources & further reading

Related: Too Many Open Files Is Almost Never a ulimit Problem

#SRE#Linux#Docker#Kubernetes#Postgres#Troubleshooting