Unable to GC store after DB fail because of full disk

Hi folks,

I made a mistake in building something on NixOS that filled the whole disk. After that, I ran nix store gc which was another mistake since I got an output that there was data to remove but I also got an SQLite error due to full disk.

I solved that by removing systemd journal logs and running nix store gc and thankfully I didn’t break anything and the NixOS instance still works just fine (thank you, developers!!!).

I have 2 almost identical NixOS instances. Looking at the one that had this problem it’s clear that some Nix paths were supposed to be removed but they were not deleted. In other words both NixOS instances have almost identical generations, but the other NixOS instance has less data in /nix even after running nix store gc on both of them.

Could you please tell me, if is it possible to properly GC the first one too? Or maybe somehow fix the DB?

Thank you.

If you’re not getting actual errors, it’s unlikely for the DB to be corrupt.

You should rather be looking for gcroots keeping some path alive that you don’t actually need anymore.

I have

alias nix-stray-roots='nix-store --gc --print-roots | grep -vE "^(/nix/var|/run/\w+-system|\{memory|\{censored|/proc/maps/)"'

for this purpose.

1 Like

Thank you for the answer!

I’m not getting DB errors. I can rebuild the system without problem.

I’ve just run alias nix-stray-roots='nix-store --gc --print-roots | grep -vE "^(/nix/var|/run/\w+-system|\{memory|\{censored|/proc/maps/)"' and I get a large number of paths. 1831 on the broken NixOS and 1821 on the other one. Should I compare the instances and run nix store delete to remove paths that don’t need to be kept?

I’m a bit confused what you mean. That command should output a few dozen entries at max, I’m not sure where you are getting these numbers from.

nix store delete has nothing to do with this. You remove the gcroot and then run a regular gc.

On my NixOS 24.05 the grep needs a change. For example:
nix-store --gc --print-roots | grep -E '^/proc/[0-9]+/maps' | wc -l
1432

since I’m getting a lot of paths like:
/proc/9990/maps -> /nix/store/xczcfjk4fxqf5svr4nm4w911pzilpvsa-php-fileinfo-8.2.23

Maybe like this:
nix-store --gc --print-roots | grep -vE "^(/nix/var|/run/\w+-system|\{memory|\{censored|/proc/)"
and I get only two paths:

/root/.cache/nix/flake-registry.json -> /nix/store/5bs7lbd1fk22w7bzdd8d6fvysnyzgw35-flake-registry.json
/root/.local/state/home-manager/gcroots/current-home -> /nix/store/2sc1bqflwmd49zwnvxggk4syljgwqagz-home-manager-generation

Ah, you’re running this as root, that’s why you’re getting more output that my regex doesn’t account for.

Run the command as your regular user on both machines; that’s where gcroots are likely to have been made.