Skip to content

Instantly share code, notes, and snippets.

@coopmoney
Last active December 18, 2025 11:47
Show Gist options
  • Select an option

  • Save coopmoney/a80aa9d2a385ff3956182ad66b50c73c to your computer and use it in GitHub Desktop.

Select an option

Save coopmoney/a80aa9d2a385ff3956182ad66b50c73c to your computer and use it in GitHub Desktop.
Debugging nix flake stability / reproducibilty
# 📆 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.
---
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