Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show stack trace above error message with innermost first #7334

Merged
merged 4 commits into from Dec 12, 2022

Conversation

chaoflow
Copy link
Member

@chaoflow chaoflow commented Nov 22, 2022

fixes #5278

When debugging nix expressions the outermost trace tends to be more useful
than the innermost. It is therefore printed last to save developers from
scrolling.

Same rationale for displaying the error message after the stack trace.

@chaoflow chaoflow marked this pull request as draft November 22, 2022 14:25
@domenkozar
Copy link
Member

cc @bburdette

@chaoflow chaoflow changed the title WIP: Don't reverse stack trace when showing Don't reverse stack trace when showing Nov 22, 2022
@chaoflow
Copy link
Member Author

@edolstra @domenkozar @DavHau This is ready. I think it would be great to show the utmost trace / code location even without --show-trace and there is code that looks like it's supposed to do that. Does anybody understand why that does not trigger? Shall we let it use the last einfo.traces instead?

@chaoflow chaoflow marked this pull request as ready for review November 22, 2022 17:58
@fricklerhandwerk
Copy link
Contributor

@chaoflow please add a brief description in the top post so the Nix team can slate this for review. Linking to an issue is good, but it requires clicking around, and we found it really helpful to see at a glance what the change is about why it is made.

My personal note: I would like to see the rationale for the change in the commit messages, since GitHub issues and pull requests are practically inaccessible through Git history unless linked explicitly - and who knows how long they will exist. Writing those first and then re-using the text in the pull request description makes the above requirement trivial.

@chaoflow
Copy link
Member Author

@fricklerhandwerk Thanks you for the feedback, I updated commit messages and PR description accordingly.

@chaoflow chaoflow changed the title Don't reverse stack trace when showing Show stack trace above error message with innermost first Nov 23, 2022
@kjeremy
Copy link

kjeremy commented Nov 23, 2022

Can you show a before and after here?

@chaoflow
Copy link
Member Author

@kjeremy

before

❯ nix build
error: getting status of '/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/.version': No such file or directory
(use '--show-trace' to show detailed location information)
❯ nix build --show-trace
error: getting status of '/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/.version': No such file or directory

       … while realising the context of path '/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/.version'

       at /nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/flake.nix:12:17:

           11|
           12|       version = builtins.readFile ./.version + versionSuffix;
             |                 ^
           13|       versionSuffix =

       … while evaluating the attribute 'name'

       at /nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/flake.nix:288:13:

          287|           nix = with final; with commonDeps { inherit pkgs; }; currentStdenv.mkDerivation {
          288|             name = "nix-${version}";
             |             ^
          289|             inherit version;

       … while evaluating anonymous lambda

       at /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/lib/strings.nix:820:3:

          819|   in
          820|   string:
             |   ^
          821|   # First detect the common case of already valid strings, to speed those up

       … from call site

       at /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:295:9:

          294|         in
          295|         lib.strings.sanitizeDerivationName (
             |         ^
          296|           if attrs ? name

       … while evaluating the derivation attribute 'name'

       at /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:278:7:

          277|     // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
          278|       name =
             |       ^
          279|         let

after

❯ ../outputs/out/bin/nix --extra-experimental-features nix-command --extra-experimental-features flakes build
error: getting status of '/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/.version': No such file or directory
(use '--show-trace' to show detailed location information)
❯ ../outputs/out/bin/nix --extra-experimental-features nix-command --extra-experimental-features flakes build --show-trace
error:
       … while evaluating the derivation attribute 'name'

       at /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:278:7:

          277|     // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
          278|       name =
             |       ^
          279|         let

       … from call site

       at /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:295:9:

          294|         in
          295|         lib.strings.sanitizeDerivationName (
             |         ^
          296|           if attrs ? name

       … while evaluating anonymous lambda

       at /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/lib/strings.nix:820:3:

          819|   in
          820|   string:
             |   ^
          821|   # First detect the common case of already valid strings, to speed those up

       … while evaluating the attribute 'name'

       at /nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/flake.nix:288:13:

          287|           nix = with final; with commonDeps { inherit pkgs; }; currentStdenv.mkDerivation {
          288|             name = "nix-${version}";
             |             ^
          289|             inherit version;

       … while realising the context of path '/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/.version'

       at /nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/flake.nix:12:17:

           11|
           12|       version = builtins.readFile ./.version + versionSuffix;
             |                 ^
           13|       versionSuffix =

       getting status of '/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/.version': No such file or directory

@domenkozar
Copy link
Member

@edolstra 🙏

@edolstra edolstra added UX The way in which users interact with Nix. Higher level than UI. error-messages Confusing messages and better diagnostics labels Nov 24, 2022
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/tweag-nix-dev-update-40/23480/1

src/libutil/error.cc Outdated Show resolved Hide resolved
@Ericson2314
Copy link
Member

Ericson2314 commented Nov 28, 2022

We noticed that … from call site no longer made sense with the flipped order.

To catch such things I did

git grep -l 'makeDebugTraceStacker\|addErrorTrace\|addTrace'

and I came up with this diff: 6a36e18. There is certainly more thing we ought to change, but I think this is sufficient to make this PR at least make nothing worse than today. I would be happy doing the rest in follow-up PRs.

@fricklerhandwerk
Copy link
Contributor

Triaged in Nix team meeting on 2022-11-25:

  • @edolstra: wondering if error messages are still correct when flipping the error
    • @Ericson2314: I think the "whiles" can go before or after in English. We're in luck!

-> assigned to @fricklerhandwerk

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2022-11-25-nix-team-meeting-minutes-11/23601/1

Copy link
Contributor

@fricklerhandwerk fricklerhandwerk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed in Nix team meeting 2022-11-28:

complete discussion
  • @roberth: at call site is a regression because the grammar doesn't make sense any more in that order
  • @fricklerhandwerk: remove the attempt of imitating speech and make it a string of information bits
    • it has to be readable in both directions, after all
  • @Ericson2314: should merge this as is and open an issue fixing the presentation minutiae
    • don't want to make author do ever more additional things and get frustrated in the process
  • @fricklerhandwerk: this is again a UX issue which could be handled by experts much better
    • we agree that the new order is obviously more suitable for finding the right information

Decision: @chaoflow This is good, only a few cosmetic fixups needed to improve readability. See the suggestions and please use @Ericson2314's diff to change the strings denoting the current action.

It should eventually look something like this, but we do this incrementally once this PR is merged:

❯ ../outputs/out/bin/nix --extra-experimental-features nix-command --extra-experimental-features flakes build
error: getting status of '/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/.version': No such file or directory
(use '--show-trace' to show detailed location information)
❯ ../outputs/out/bin/nix --extra-experimental-features nix-command --extra-experimental-features flakes build --show-trace
evaluation trace:
---
evaluating the derivation attribute 'name'

/nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:278:7:

  277|     // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
  278|       name =
     |       ^
  279|         let
---
evaluating call site

/nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:295:9:

  294|         in
  295|         lib.strings.sanitizeDerivationName (
     |         ^
  296|           if attrs ? name
---
evaluating the attribute 'name'

/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/flake.nix:288:13:

  287|           nix = with final; with commonDeps { inherit pkgs; }; currentStdenv.mkDerivation {
  288|             name = "nix-${version}";
     |             ^
  289|             inherit version;
---
realising the context of path '/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/.version'

/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/flake.nix:12:17:

   11|
   12|       version = builtins.readFile ./.version + versionSuffix;
     |                 ^
   13|       versionSuffix =
---
getting status of '/nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/.version': No such file or directory

src/libutil/error.cc Outdated Show resolved Hide resolved
src/libutil/error.cc Show resolved Hide resolved
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2022-11-28-nix-team-meeting-minutes-12/23730/1

@bew
Copy link
Contributor

bew commented Dec 5, 2022

Slightly off-topic, on the formatting of the stack trace, can be dealt with in another PR

I have one concern with the suggested formatting in #7334 (review) : the blank lines and the --- seems to group together the source peek and the next frame message.

I'd like to suggest something like this (slightly inspired from Rust's error trace):

evaluating the derivation attribute 'name'

    --> /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:278:7
     |
  277|     // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
  278|       name =
     |       ^
  279|         let

evaluating call site

    --> /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:295:9
     |
  294|         in
  295|         lib.strings.sanitizeDerivationName (
     |         ^
  296|           if attrs ? name

evaluating the attribute 'name'

    --> /nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/flake.nix:288:13
     |
  287|           nix = with final; with commonDeps { inherit pkgs; }; currentStdenv.mkDerivation {
  288|             name = "nix-${version}";
     |             ^
  289|             inherit version;
  • Remove last : on /nix/store/.../foo.nix:line:col (not really needed with this format)
  • the only text that is at column 1 is a start of a new frame, everything else is nicely indented under it
  • link the path to the source peek (no blank line in between that breaks the frame reading flow)

I believe this format is easier to skim through with quick reading.

@fricklerhandwerk
Copy link
Contributor

@bew sure, we can still improve cosmetics. Maybe get in touch with @Ericson2314 who wanted to address this more generally.

the blank lines and the --- seems to group together the source peek and the next frame message.

Not sure what you mean. But I may be wrong and grossly misreading to code...

@bburdette
Copy link
Contributor

I think he means the lack of spaces between the error location and the next 'evaluating' phrase could lead some folks to think they belong together. Here "evaluating call site" might be interpreted at first glance as belonging to the code above it.


/nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:278:7:

  277|     // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
  278|       name =
     |       ^
  279|         let
---
evaluating call site

With the format proposed by @bew, having a colon at the end of the 'evaluating' line would help reduce ambiguity about what belongs to what:

evaluating the derivation attribute 'name':

    --> /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:278:7
     |
  277|     // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
  278|       name =
     |       ^
  279|         let

@Ericson2314
Copy link
Member

Ericson2314 commented Dec 5, 2022

If there is some disagreement on what the best formatting is, then I recommend we just add 6a36e18, simplify the for loop per the line comment, and circle back later.

That keeps this PR just the uncontroversial stuff about traceback order along with the bare minimum changing the messages to not regress.

@chaoflow
Copy link
Member Author

chaoflow commented Dec 5, 2022

Building on @bew 's proposal but reducing some whitespace:

Evaluating the derivation attribute 'name' at
  /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:278:7
     |
  277|     // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
  278|       name =
     |       ^
  279|         let

Evaluating call site at
  /nix/store/vp7k2rx0w0yidr691mmq62z6hragpbzx-source/pkgs/stdenv/generic/make-derivation.nix:295:9
     |
  294|         in
  295|         lib.strings.sanitizeDerivationName (
     |         ^
  296|           if attrs ? name

Evaluating the attribute 'name' at
  /nix/store/qz0f0nw8siij1xw7cdk4n20xga6frhrs-source/broken/flake.nix:288:13
     |
  287|           nix = with final; with commonDeps { inherit pkgs; }; currentStdenv.mkDerivation {
  288|             name = "nix-${version}";
     |             ^
  289|             inherit version;

@fricklerhandwerk
Copy link
Contributor

fricklerhandwerk commented Dec 5, 2022

@chaoflow I like this a lot. I'd only propose keeping capitalisation out, because it makes reshuffling information harder. We already noticed that assuming too much grammatical structure can be a hindrance to change.

Would be great if you make that change, either here or in a follow-up PR (which I prefer because small changes are easier to review).

@chaoflow
Copy link
Member Author

chaoflow commented Dec 9, 2022

@Ericson2314 thx - got it! Changing the loop entails a bit more work, will look at it later.

Copy link
Member

@Ericson2314 Ericson2314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much! This looks good to me now. The rest we can do in follow-up PRs.

@Ericson2314
Copy link
Member

Asking @roberth for a review since it was he that found those "from ..." messages that were the issue to begin with.

Copy link
Contributor

@fricklerhandwerk fricklerhandwerk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build broke, please check again.

src/libutil/error.cc Outdated Show resolved Hide resolved
src/libutil/error.cc Outdated Show resolved Hide resolved
chaoflow and others added 4 commits December 12, 2022 18:41
When debugging nix expressions the outermost trace tends to be more useful
than the innermost. It is therefore printed last to save developers from
scrolling.
Save developers from scrolling by displaying the error message last,
below the stack trace.
Make everything be in the form "while ..." (most things were already),
and in particular *don't* use other propositions that must go after or
before specific "while ..." clauses to make sense.
@fricklerhandwerk fricklerhandwerk merged commit edb54c6 into NixOS:master Dec 12, 2022
@Ericson2314
Copy link
Member

Yay! @chaoflow you up for the reformatting follow-up PR now?

@chaoflow chaoflow deleted the stack-trace-order branch December 13, 2022 13:45
@chaoflow
Copy link
Member Author

@Ericson2314 Yes, happy to.

@domenkozar
Copy link
Member

Follow up: #7494

@roberth roberth mentioned this pull request Jan 20, 2023
3 tasks
@roberth roberth added the language The Nix expression language; parser, interpreter, primops, evaluation, etc label Jul 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error-messages Confusing messages and better diagnostics language The Nix expression language; parser, interpreter, primops, evaluation, etc UX The way in which users interact with Nix. Higher level than UI.
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Reverse order of stack printed by --show-trace