lix/doc/manual/rl-next/better-attrpath-errors.md
Qyriad 14bf54bd39 trace which part of foo.bar.baz errors
Turns errors like:

let
  somepkg.src = throw "invalid foobar";
in somepkg.src.meta

error:
       … while evaluating the attribute 'src.meta'
         at «string»:2:3:
            1| let
            2|   somepkg.src = throw "invalid foobar";
             |   ^
            3| in somepkg.src.meta

       … while calling the 'throw' builtin
         at «string»:2:17:
            1| let
            2|   somepkg.src = throw "invalid foobar";
             |                 ^
            3| in somepkg.src.meta

       error: invalid foobar

into errors like:

let
  somepkg.src = throw "invalid foobar";
in somepkg.src.meta

error:
       … while evaluating the attribute 'src.meta'
         at «string»:2:3:
            1| let
            2|   somepkg.src = throw "invalid foobar";
             |   ^
            3| in somepkg.src.meta

       … while evaluating 'somepkg.src' to select 'meta' on it
         at «string»:3:4:
            2|   somepkg.src = throw "invalid foobar";
            3| in somepkg.src.meta
             |    ^

       … while calling the 'throw' builtin
         at «string»:2:17:
            1| let
            2|   somepkg.src = throw "invalid foobar";
             |                 ^
            3| in somepkg.src.meta

       error: invalid foobar

And for type errors, from:

let
  somepkg.src = "I'm not an attrset";
in somepkg.src.meta

error:
       … while evaluating the attribute 'src.meta'
         at «string»:2:3:
            1| let
            2|   somepkg.src = "I'm not an attrset";
             |   ^
            3| in somepkg.src.meta

       … while selecting an attribute
         at «string»:3:4:
            2|   somepkg.src = "I'm not an attrset";
            3| in somepkg.src.meta
             |    ^

       error: expected a set but found a string: "I'm not an attrset"

into:

let
  somepkg.src = "I'm not an attrset";
in somepkg.src.meta

error:
       … while evaluating the attribute 'src.meta'
         at «string»:2:3:
            1| let
            2|   somepkg.src = "I'm not an attrset";
             |   ^
            3| in somepkg.src.meta

       … while selecting 'meta' on 'somepkg.src'
         at «string»:3:4:
            2|   somepkg.src = "I'm not an attrset";
            3| in somepkg.src.meta
             |    ^

       error: expected a set but found a string: "I'm not an attrset"

For the low price of an enumerate() and a lambda you too can have the
incorrect line of code actually show up in the trace!

Change-Id: Ic1491c86e33c167891bdac9adad6224784760bd6
2024-07-04 17:42:35 -06:00

4.4 KiB

synopsis cls credits category
Trace which part of a `foo.bar.baz` expression errors 1505, 1506 Qyriad Improvements

Previously, if an attribute path selection expression like linux_4_9.meta.description it wouldn't show you which one of those parts in the attribute path, or even that that line of code is what caused evaluation of the failing expression. The previous error looks like this:

pkgs.linuxKernel.kernels.linux_4_9.meta.description

error:
       … while evaluating the attribute 'linuxKernel.kernels.linux_4_9.meta.description'
         at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:5:
          277|   } // lib.optionalAttrs config.allowAliases {
          278|     linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
             |     ^
          279|     linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";

       … while calling the 'throw' builtin
         at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:17:
          277|   } // lib.optionalAttrs config.allowAliases {
          278|     linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
             |                 ^
          279|     linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";

       error: linux 4.9 was removed because it will reach its end of life within 22.11

Now, the error will look like this:

pkgs.linuxKernel.kernels.linux_4_9.meta.description

error:
       … while evaluating the attribute 'linuxKernel.kernels.linux_4_9.meta.description'
         at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:5:
          277|   } // lib.optionalAttrs config.allowAliases {
          278|     linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
             |     ^
          279|     linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";

       … while evaluating 'pkgs.linuxKernel.kernels.linux_4_9' to select 'meta' on it
         at «string»:1:1:
            1| pkgs.linuxKernel.kernels.linux_4_9.meta.description
             | ^

       … caused by explicit throw
         at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:17:
          277|   } // lib.optionalAttrs config.allowAliases {
          278|     linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
             |                 ^
          279|     linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";

       error: linux 4.9 was removed because it will reach its end of life within 22.11

Not only does the line of code that referenced the failing attribute show up in the trace, it also tells you that it was specifically the linux_4_9 part that failed.

This includes if the failing part is a top-level binding:

let
  inherit (pkgs.linuxKernel.kernels) linux_4_9;
in linux_4_9.meta.description
error:
       … while evaluating 'linux_4_9' to select 'meta.description' on it
         at «string»:3:4:
            2|   inherit (pkgs.linuxKernel.kernels) linux_4_9;
            3| in linux_4_9.meta.description
             |    ^

       … while evaluating the attribute 'linux_4_9'
         at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:5:
          277|   } // lib.optionalAttrs config.allowAliases {
          278|     linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
             |     ^
          279|     linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";

       … caused by explicit throw
         at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:17:
          277|   } // lib.optionalAttrs config.allowAliases {
          278|     linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
             |                 ^
          279|     linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";

       error: linux 4.9 was removed because it will reach its end of life within 22.11