NixOS & Configuration

Garbage collection frees less space than expected

The Nix store remains large after collection because roots retain closures. Inspect generations and result links before deleting recovery paths or store files.

On this page
  1. Symptoms & scope
  2. Possible causes
  3. Diagnose safely
  4. Evidence-guided next steps
  5. References & review
  6. Related problems

Symptoms & scope

  • Collection frees little despite a large /nix/store.
  • Builds run out of filesystem space while many old outputs remain referenced.

Relevant environment

Nix store garbage collection, profile generations and direct or indirect GC roots.

Possible causes

These are possible explanations, not a confirmed diagnosis. Several independent faults can coexist.

  • Profiles, previous system generations or project result links may retain large dependency closures.
  • Filesystem usage can include data outside the store; store size is not identical to reclaimable space.

Diagnose safely

Run one command at a time in the relevant session. Read the explanation first. Uppercase placeholders need your own values; tools and privileges vary by distribution. These commands are displayed here and never executed by the website.

Check 1

The --print-roots suboperation lists roots instead of collecting; do not omit that flag.

nix-store --gc --print-roots

Interpret the result: Profile and result-link roots explain retained closures. Roots may be indirect and belong to users or projects other than this shell.

Check 2

Lists system-profile generations without switching or deleting; profile visibility may be restricted.

nix-env --profile /nix/var/nix/profiles/system --list-generations

Interpret the result: Compare older generations with the recovery versions you intentionally keep. Current user-profile generations are a separate root set.

Check 3

Reads filesystem capacity and does not scan or modify store files.

df -h /nix/store

Interpret the result: Low available space may also come from other directories on that filesystem. Check inode exhaustion separately when allocation fails despite free bytes.

Evidence-guided next steps

Retire only obsolete roots

If a project result link or profile generation is confirmed obsolete, remove it through that project's or profile's supported lifecycle, then collect unreferenced store paths. Keep current, booted and a known-good recovery generation intentionally.

Precautions: Removing roots can make outputs collectible permanently. Never delete arbitrary /nix/store files or the whole gcroots directory.

Recovery / rollback: Before collection, restore a removed link if its store target still exists. After collection, recovery requires a rebuild or a verified available substitute.

Did this solution help you?

Share this solution#

Set an explicit retention and capacity budget

If regular builds outgrow storage, configure finite generation retention and scheduled GC suited to your recovery needs, or expand the filesystem. Inspect all user roots before assuming system-generation cleanup is sufficient.

Precautions: A removed generation is not restored just by switching back. Store cleanup does not back up mutable application data.

Recovery / rollback: Disable the new automatic policy and restore retained links while targets exist; rebuild collected outputs from saved configuration pins if needed.

Did this solution help you?

Share this solution#

References & review

This guide was prepared from primary project or distribution sources and reviewed on the date shown. This is an editorial source check, not evidence that a fix was reproduced on your hardware. Diagnostic log examples are synthetic fixtures. Version-dependent details must be checked against your installed release.