Skip to main content

nospace

nospace is a Linux-only CLI that explains a deliberately small set of filesystem-related failures using syscall and kernel evidence. It returns UNKNOWN instead of guessing when the evidence does not support a diagnosis.

$ nospace /var/lib/app
Target: /var/lib/app
Filesystem: /dev/nvme0n1p2
Mount: /var
Type: ext4

Checks:
  file probe       ENOSPC during create
  available space  82.4 GiB
  free inodes      0
  inotify init     OK
  inotify watch    OK
  read-only        no
  mount option ro  no

CONFIRMED: inode exhaustion

Evidence, not likelihood

The initial classifier confirms only:

  • Block exhaustion: a create/write/fsync probe returned ENOSPC and statvfs reports zero bytes available to the current user.
  • Inode exhaustion: that probe returned ENOSPC, the filesystem reports zero free inodes, and the filesystem has fixed inode accounting supported by nospace (currently ext2/3/4).
  • Read-only filesystem: the create probe returned EROFS.
  • Inotify exhaustion: file creation succeeded and inotify_add_watch returned ENOSPC.

Deleted-open files are detected by st_nlink == 0, grouped by device/inode, and measured using allocated blocks rather than apparent file size. They are reported as contributing evidence only when the filesystem has no available blocks.

Anything else is UNKNOWN.

When every supported active probe succeeds, the result is no_supported_failure in JSON and OK: no supported failure detected in text. This is deliberately narrower than claiming that the filesystem is healthy.

Install

The Python distribution is called nospace-cli, but it installs the native nospace executable. It does not require Cargo or compile Rust on the user's machine.

pipx install nospace-cli
# or
uv tool install nospace-cli
# or, inside a virtual environment
python -m pip install nospace-cli

Do not run pip install nospace: that PyPI name belongs to an unrelated file renaming utility.

Prebuilt wheels target glibc-based Linux on x86-64 and ARM64. Other platforms, including musl-based distributions such as Alpine Linux, fail installation instead of attempting a source build. nospace is Linux-only.

Usage

nospace PATH
nospace PATH --json
nospace PATH --verbose
nospace PATH --no-probe

--verbose includes the observed inotify watch total for the current UID, the configured max_user_watches limit and per-process watch counts. If process visibility is incomplete, the observed total is explicitly labeled as a lower bound.

The target must exist. If it is a file, nospace creates its temporary probe in the parent directory.

--no-probe performs no file creation and adds no inotify watch. It still reads filesystem statistics and accessible /proc information, but usually cannot produce a confirmed diagnosis.

What it inspects

  • The exact mount ID from statx(STATX_MNT_ID), matched to /proc/self/mountinfo
  • statvfs block, inode and read-only state
  • A collision-safe openat(O_CREAT | O_EXCL) → unlink → write → fsync probe
  • inotify_init1 and inotify_add_watch separately
  • Inotify limits and visible watches belonging to the current UID
  • Accessible deleted-open regular files on the target filesystem

/proc inspection can be incomplete because of permissions or because a process exits during the scan. That state is explicit in text and JSON output; inaccessible processes are never counted as zero usage. Running as root reveals more process evidence but does not change the classification rules.

Safety

nospace never deletes user files, kills processes, changes limits, remounts a filesystem, changes permissions or performs cleanup. Its only default mutations are a uniquely named one-byte temporary file that is immediately removed and a temporary inotify watch that is closed before exit.

The probe unlinks its random pathname immediately after opening it, then calls fsync so delayed-allocation failures are observed without leaving a named probe behind. If that early unlink fails, the exact failure is reported.

Unsupported causes

Version 0.1 intentionally does not diagnose:

  • user, group or project quotas (EDQUOT or filesystem-specific behavior)
  • Btrfs data/metadata allocation
  • overlay upper-layer exhaustion
  • network-filesystem server limits
  • oversized-directory constraints
  • filesystem corruption

These remain UNKNOWN even when a human might have a good hypothesis.

Build and test

cargo build --release
cargo test --all-targets
cargo clippy --all-targets -- -D warnings

Safe tests run on any Linux machine. The block, inode, read-only, nested-mount, inotify and deleted-open contribution tests require a disposable Linux VM with root access:

NOSPACE_EPHEMERAL_VM=1 sudo -E tests/privileged.sh

The script refuses to run without the explicit marker. It mounts disposable filesystems under a fresh /tmp directory and temporarily lowers an inotify limit; therefore it must never be run on a developer workstation or shared host.

Why not parse df, findmnt, or lsof?

Those tools are useful, but their human-oriented output is not a stable evidence API. nospace calls the relevant interfaces directly and keeps collection separate from the pure deterministic classifier.

Release files for nospace-cli 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for nospace-cli 0.1.2
File Interpreter ABI Platform
nospace_cli-0.1.2-py3-none-manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64 Details
nospace_cli-0.1.2-py3-none-manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.28+ ARM64 Details

Total release size: 505.4 kB

Release files / nospace_cli-0.1.2-py3-none-manylinux_2_28_x86_64.whl

Download URL nospace_cli-0.1.2-py3-none-manylinux_2_28_x86_64.whl
Size 259.5 kB
Tags Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
78d649af668ae2f069d2edf8982d7c567ec4929f82d60adea2d177954ed8a2bc
BLAKE2b-256 checksum
How to use checksums
aaa7eedf857669e57a0fb1d7755f140f90d4907c0123d328dfce3f61742d110d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / nospace_cli-0.1.2-py3-none-manylinux_2_28_aarch64.whl

Download URL nospace_cli-0.1.2-py3-none-manylinux_2_28_aarch64.whl
Size 245.9 kB
Tags Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
5ef0f38873ab4a43f9d166eb6960c55c42d13bc56d91a02c93777303ad3e5ec7
BLAKE2b-256 checksum
How to use checksums
00e434263749bcd7b2397d4221c75e44b052028959aefca01780ac3420c32888
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page