nix icon indicating copy to clipboard operation
nix copied to clipboard

Show derivation "stack" that was attempted to eval when eval is aborted

Open Atemu opened this issue 1 year ago • 2 comments

Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

It's a somewhat common case to have a declarative environment "break" on you because some package has been marked as broken/insecure/whatever upstream. In the error message, you'll see the package's name which is useful but, quite often, it's not a "direct" dependency; it's a transitive dependency, not a dependency you explicitly declared your desired closure to depend on. From this point on, it's near impossible to figure out which of your actual explicit dependencies depends on the broken package.
Sometimes, you can deduce this from tedious analysis of the file names in the stack trace but even that doesn't always work and it's easy to miss.

Describe the solution you'd like A clear and concise description of what you want to happen.

I don't know whether this is even remotely possible (please chime in if you know better) but I had this idea and I wanted to put it out there:

When eval is aborted for some reason, Nix should print (or have the option to print) a "stack" with some limited information about the tree of derivations currently being evaluated. This would look similar and have a similar function as why-depends but on the eval level, not the output path runtime dependency level.

Let's say we have three derivations top, direct and trans. top depends on direct and direct on trans. trans throws.
When you try to eval top, you'd have no way of knowing which of your direct dependencies caused the eval to abort (in this case it's trivial but in most real cases it's not). To aid the user in figuring it out, something like the following should be printed:

error: evaluation aborted while trying to evaluate:
top-6.9
└─direct-4.2.0
  └─trans-1.33.7 (error)
<Custom throw text here>

In my mental model how this would work is that Nix evals from the root drv on recursively, so at the time of encountering an expression that would cause it to abort, the evaluator must somehow know the path from the root drv to the currently being evaluated drv. If it didn't eval the names of those drvs yet, it'd try to do so for the purpose of displaying them in the tree output.

Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.

  • The file containing the derivation could be printed instead/also
  • The name of the drv could itself throw. In that case, printing a stand-in would be better than nothing.

Additional context Add any other context or screenshots about the feature request here.

  • Only partial info on the derivations can be printed because a full evaluation is, by definition, not possible; all derivations in this list either throw themselves or have a dependency which throws.
  • It may be interesting to print some further drv metadata such as the platform it's for. I've had confusing cases where I was able to deduce the failing drv's name but it'd eval and build. Turned out it failed to eval because of some property related to its system.

Priorities

Add :+1: to issues you find important.

Atemu avatar Feb 21 '24 23:02 Atemu

We technically already have some of that info buried down in the stack trace, but it is indeed one of the most important bits of information in many cases, and having it more apparent could be very good:

$ nix-build --expr 'with import <nixpkgs> { config.allowUnfree = false; }; writeText "bar" (writeText "foo" hello-unfree)' --show-trace
error:  
---- stuff ----
       … while evaluating derivation 'bar'                      
         whose name attribute is located at /nix/store/5hwz775f3grzikafj1sbwx4lqkjwqswb-source/pkgs/stdenv/generic/make-derivation.nix:348:7
---- stuff ----
       … while evaluating derivation 'foo'
         whose name attribute is located at /nix/store/5hwz775f3grzikafj1sbwx4lqkjwqswb-source/pkgs/stdenv/generic/make-derivation.nix:348:7
---- stuff ----
       error: Package ‘example-unfree-package-1.0’ in /nix/store/5hwz775f3grzikafj1sbwx4lqkjwqswb-source/pkgs/applications/misc/hello-unfree/defaul
t.nix:19 has an unfree license (‘unfree’), refusing to evaluate.

I'm not clear what exactly we would want. Maybe as a good first approach we could have the “truncated” stack trace (without --show-trace) only show these while evaluating derivation 'blah' lines. I remember some recent discussions about what to print by default, that could be a good answer if the error happens while evaluating a derivation.

cc @9999years

thufschmitt avatar Feb 22 '24 16:02 thufschmitt

Either instead of or in addition to truncating, something like the suggested tree-style output could be appended to the trace; something like:

note: occurred in the evaluation of the following derivations:
top-6.9
└─direct-4.2.0
  └─trans-1.33.7 (error)

Qyriad avatar Feb 23 '24 20:02 Qyriad