What is writeTextFile.checkPhase doing? Need help debugging `Is a directory` error


I am running into a small issue when building my home manager config. In particular, when I try to build my get-active-monitors script, I seem to hit a snag during the check phase (commenting it out at least seems to get things to build?). Here is an example of what the error looks like:

error: builder for '/nix/store/zzg44xnsdwkpfhbvqpgpjfvxl8dz3zb4-get_active_monitors.drv' failed with exit code 126;
       last 1 log lines:
       > /nix/store/m4fvwf1fyqn2wblrik2imyjzlqcmnzda-get_active_monitors: /nix/store/m4fvwf1fyqn2wblrik2imyjzlqcmnzda-get_active_monitors: Is a directory
       For full logs, run 'nix log /nix/store/zzg44xnsdwkpfhbvqpgpjfvxl8dz3zb4-get_active_monitors.drv'.
error: 1 dependencies of derivation '/nix/store/pyb0fj4mizmgdafl07n86gh40cgciz9n-bspwmrc.drv' failed to build
error: 1 dependencies of derivation '/nix/store/ldxfwlppkc8w2b51s7lrgjr410qdk3a2-home-manager-files.drv' failed to build
error: 1 dependencies of derivation '/nix/store/bv9d0vgph41g3m1kg02qyjjjqi72yqka-home-manager-generation.drv' failed to build

I am not quite sure what this means, so any help is appreciated.


The original used $target, which would be the actual file written. You’re trying to use $out, which might or might not be the same as $target. They differ in your case–$out is the package’s root directory. It worked with your old writeShellScript because you weren’t specifying a destination.

An aside: you may also find [resholve.writeScript or resholve.writeScriptBin (doc) helpful. resholve takes roughly the opposite approach to injecting a PATH–it figures out which command-words are external dependencies, blocks the build until you specify packages containing all of them, and then rewrites the invocations to use store paths.

It can be a little picky–which might be overkill for a short script you can hand-audit–but it’s pretty good at shaking loose overlooked dependencies.

1 Like

To be clear, I blindly copied checkPhase from an earlier implementation of writeShellScriptBin in nixpkgs. I really don’t know what it does or what it is complaining about

I’m unsure…

  • is this just a clarification because I used “You’re” and “your”? (I realize these are modeled on the nixpkgs functions–all I mean here is that it’s code you committed to your own repo…)
  • or does this mean the interpretation didn’t help get the checkPhase working? Maybe because there’s a mismatch between some combination of the current source I referenced, the one you cribbed from, and the one your flake pins? IDK :slight_smile:
1 Like

I may be especially poor at communicating, so I apologize. What I mean is that I think you are talking a bit over my head (especially this late in the evening :joy:). If you don’t mind, can we start at a very basic level? What is the original checkPhase script ${stdenv.shell} -n $out even trying to accomplish? Why does it complain when I try to modify path?

Some fraction of shells (most importantly bash, here) perform a basic syntax validity check when the -n flag is present.

It’s just smoke-testing the script.

1 Like

This bit is what my original comment is trying to explain. The version in your repo is testing $out, which it expects to be a script. Specifying the bin/filename destination, however, causes $out to be created as a directory that will include the script at that sub-path.

1 Like

I see that now. And in fact it seems like the original accounts for that. Thanks for spending the time to clarify it for me :grinning: !

I have one more quick and simple question though if you don’t mind. What is $target and where is it defined?

I am not sure if it was named $target at the nixpkgs commit you have pinned. It looks like it changed in late 2021: tests.trivial-builders.overriding: update after shellDryRun · NixOS/nixpkgs@10ec5da · GitHub

1 Like