Last active
December 18, 2025 11:47
-
-
Save coopmoney/a80aa9d2a385ff3956182ad66b50c73c to your computer and use it in GitHub Desktop.
Debugging nix flake stability / reproducibilty
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 📆 2025-12-07 | |
| step-by-step flow to discover what's causing the derivation to change: | |
| ## Step 1: Capture the current shell derivation path | |
| ```bash | |
| devenv build shell 2>&1 | grep -oE '/nix/store/[a-z0-9]+-devenv-shell' | |
| ``` | |
| Save this path: | |
| ```bash | |
| OLD_SHELL=$(devenv build shell 2>&1 | grep -oE '/nix/store/[a-z0-9]+-devenv-shell') | |
| echo $OLD_SHELL | |
| ``` | |
| ## Step 2: Wait/change nothing, rebuild, capture new path | |
| ```bash | |
| NEW_SHELL=$(devenv build shell 2>&1 | grep -oE '/nix/store/[a-z0-9]+-devenv-shell') | |
| echo $NEW_SHELL | |
| ``` | |
| If `$OLD_SHELL == $NEW_SHELL`, the derivation is stable. If different, continue. | |
| ## Step 3: Diff the derivation files | |
| ```bash | |
| nix derivation show $OLD_SHELL > /tmp/old.drv.json | |
| nix derivation show $NEW_SHELL > /tmp/new.drv.json | |
| diff /tmp/old.drv.json /tmp/new.drv.json | |
| ``` | |
| This shows exactly which inputs changed. | |
| ## Step 4: If inputs differ, drill into the specific input | |
| The diff will show store paths that differ. For each differing input: | |
| ```bash | |
| # Example: if inputDrvs shows different paths for some-package | |
| nix derivation show /nix/store/xxx-some-package.drv > /tmp/old-input.json | |
| nix derivation show /nix/store/yyy-some-package.drv > /tmp/new-input.json | |
| diff /tmp/old-input.json /tmp/new-input.json | |
| ``` | |
| ## Step 5: Check for impure inputs | |
| Common culprits that cause instability: | |
| ```bash | |
| # Check for builtins.currentTime or builtins.currentSystem usage | |
| grep -r "builtins.currentTime\|builtins.currentSystem" tooling/nix/ | |
| # Check for builtins.getEnv (impure) | |
| grep -r "builtins.getEnv" tooling/nix/ | |
| # Check for filterSource or path inputs that include changing files | |
| grep -r "filterSource\|cleanSource\|path =" tooling/nix/ | |
| ``` | |
| ## Step 6: Check if git tree state affects the hash | |
| ```bash | |
| # Build with clean tree | |
| git stash | |
| CLEAN_SHELL=$(devenv build shell 2>&1 | grep -oE '/nix/store/[a-z0-9]+-devenv-shell-env') | |
| git stash pop | |
| # Build with dirty tree | |
| DIRTY_SHELL=$(devenv build shell 2>&1 | grep -oE '/nix/store/[a-z0-9]+-devenv-shell-env') | |
| echo "Clean: $CLEAN_SHELL" | |
| echo "Dirty: $DIRTY_SHELL" | |
| ``` | |
| If they differ, the dirty files are being included in the input hash. | |
| ## Step 7: Identify which files are being tracked | |
| ```bash | |
| # See what devenv considers as source inputs | |
| nix flake metadata .devenv 2>&1 | head -30 | |
| # Check the generated flake's source filtering | |
| cat .devenv/flake.nix 2>/dev/null | head -50 | |
| ``` | |
| ## Step 8: Use nix-diff for detailed comparison | |
| ```bash | |
| # Install nix-diff if needed | |
| nix-shell -p nix-diff | |
| # Compare two derivations in detail | |
| nix-diff $OLD_SHELL $NEW_SHELL | |
| ``` | |
| This gives a human-readable diff showing exactly what changed. | |
| --- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| nix path-info -rsS --closure-size $DEVENV_PROFILE | sort -k3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment