The Nix Database (db.sqlite)
The Nix Database (db.sqlite)
/nix/store is a directory tree. Nix does not discover it by walking the tree on every command. The boring default is: the daemon owns /nix/var/nix/db/db.sqlite, and you query it with nix-store / nix path-info, never with sqlite3.
Mental model
The database answers three questions:
- Is this path valid (registered, complete, not half-copied)?
- What does it reference, and what refers to it?
- Which
.drvderived it?
/nix/store/ bytes
/nix/var/nix/db/ index of those bytes
db.sqlite
schema
If you copy files into /nix/store with cp, the database does not know them. nix-store --query will not list them. GC will not preserve them. The next --verify may delete them as garbage.
The daemon holds a lock on the database. That is why two nix-build processes can run at once without corrupting registration. On a multi-user 2.35 install your account talks to the daemon; the daemon talks to SQLite.
Worked examples
Case 1: Referrers — who keeps this path alive?
nix-store -q --referrers $(nix path-info nixpkgs#ripgrep)Output (shape):
/nix/store/z1k947f6y788sfaivs931h26hsvb3506-ripgrep-14.1.1
/nix/store/…-system-path
A path with no referrers and no GC root is collectable. Profiles and result symlinks show up as referrers once they point here.
nix-store -q --referrers-closure $(nix path-info nixpkgs#hello) | wc -lThat number is “how much of the graph would notice if hello vanished,” not disk size.
Case 2: Valid path check
nix-store --query --hash $(nix path-info nixpkgs#hello)
nix-store --verify --check-contents 2>&1 | tail--verify --check-contents rehashes every registered path. It is slow; it is the tool you run after a disk scare, not every morning. Without --check-contents it only checks that the directory exists.
Output on a healthy store:
reading the Nix database...
checking path existence...
checking hashes...
No “path is corrupted” lines.
Case 3: Deriver link
nix-store -q --deriver $(nix path-info nixpkgs#hello)
nix path-info --json nixpkgs#hello | jq '.[].deriver, .[].narHash, .[].references'Output (shape):
/nix/store/…-hello-2.12.1.drv
Substituted paths (downloaded from a cache, never built here) may report unknown-deriver. That is not corruption. The bytes arrived without the .drv.
Case 4: Registration is why nix copy exists
mkdir -p /tmp/not-a-store
cp -a $(nix path-info nixpkgs#hello) /tmp/not-a-store/
nix-store -q --requisites /tmp/not-a-store/hello-* 2>&1 || trueOutput:
error: path '/tmp/not-a-store/…' is not valid
The bytes exist. Nix does not care. Register them:
nix copy --to file:///tmp/desk-cache nixpkgs#hello
nix path-info --store file:///tmp/desk-cache nixpkgs#helloThat cache has its own database. USB cp of a store directory does not.
Case 5: Where the file lives (look, don’t poke)
sudo ls -l /nix/var/nix/db/Output:
-rw-r--r-- 1 root root … db.sqlite
-rw-r--r-- 1 root root … schema
Owned by root. You do not sqlite3 this file. After filesystem damage:
sudo nix-store --verify --check-contentsThen restore missing paths from the team cache (nix copy --from …). Do not INSERT rows by hand.
The trap
The trap is opening db.sqlite in a GUI and deleting a row to “free space.” The store directory and the database then disagree. --verify will complain; GC may delete the wrong thing; the daemon may refuse to start.
The other trap is sudo rm -rf /nix/store/some-hash-… because du scared you. The database still lists the path as valid. The next build that expected those bytes fails in a way that looks like a nixpkgs bug.
Use nix-collect-garbage. Use nix-store --delete only on a path with zero referrers, and only when you mean it.
The boring rule
- Query with
nix-store -qandnix path-info. Never write SQL againstdb.sqlite. - Paths that are not registered are not Nix paths, even if they sit under
/nix/store. - After filesystem damage,
nix-store --verify --check-contents. Then restore from a cache, do not patch the DB. - Substituted artifacts may lack a deriver. That is normal.
- Delete via GC, not
rm.
Try this
nix-store -q --referrers-closure $(nix path-info nixpkgs#hello)and estimate how much of your profile depends onhello.- Run
nix-store --verifywithout--check-contents(fast existence check). Then decide whether you need the slow rehash. nix path-info --json nixpkgs#helloand identifynarHash,references, andderiverin the JSON.- Attempt
nix-store --delete $(nix path-info nixpkgs#glibc)and read the “cannot delete path because it is still alive” error. That error is the database doing its job.