Debugging binary caches not working on macOS

I’ve just started trying out IHP on macOS, and it seems the binary caches are not working: initial setup spent a long time compiling haskell packages (132 of them, if I read correctly?), and the same happens when I add any haskell packages to the nix flake.

I’m not really sure how to debug the binary cache, so I’m hoping for some help/tips.

Running ihp-new initially edited ~/.config/nix/nix.conf and updated these lines:

substituters =
trusted-public-keys =

I also tried running cachix authtoken digitallyinduced followed by cachix use digitallyinduced, with no major change (it may have changed the specific data in those files – I didn’t check before doing it).

I also added those lines to /etc/nix/nix.conf, with no change.

I think I should check whether the packages that are being built are present in the digitallyinduced cache, but I don’t know how to find out the store paths for the packages being built. (Maybe there’s a nix command I can run to find the store paths for the flake? That seems logical.)

I also saw some advice in a couple of places about restarting the nix-daemon, but I don’t know how to do this on macOS – I can’t actually tell whether the daemon is running (e.g. ps aux | rg nix doesn’t return anything for the daemon, launchctl list | rg nix shows nothing), but I assume it is running because I can install things fine with nix-env.

Well, it looks like nix flake show should be the command I need:

This command shows the output attributes provided by the flake specified by flake reference flake-url. These are the top-level attributes in the outputs of the flake, as well as lower-level attributes for some standard outputs (e.g. packages or checks).

However, trying to run this for my IHP project gives me a devenv error I’ve run into before when trying to get nix develop working:

warning: Git tree '/Users/Emily/Work/Pannal Village Hall (no git)/ihp-alternative' is dirty
│   ├───aarch64-darwin
│   │   └───default omitted (use '--all-systems' to show)
│   ├───aarch64-linux
│   │   └───default omitted (use '--all-systems' to show)
│   ├───x86_64-darwin
       … while evaluating the attribute 'optionalValue.value'
         at /nix/store/sc2fmza4wlzi16jjjmkg6rmmmf75jxmr-source/lib/modules.nix:856:5:
          856|     optionalValue =
             |     ^
          857|       if isDefined then { value = mergedValue; }

       … while evaluating a branch condition
         at /nix/store/sc2fmza4wlzi16jjjmkg6rmmmf75jxmr-source/lib/modules.nix:857:7:
          856|     optionalValue =
          857|       if isDefined then { value = mergedValue; }
             |       ^
          858|       else {};

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: Failed assertions:
       - devenv was not able to determine the current directory.

         See how to use it with flakes.

So it seems I might need to know more about devenv to figure this out?

Note: because my project is currently building (as the binary cache isn’t working, it’s building pandoc from source in another terminal), I’m trying to run my nix commands outside of the project directory so direnv doesn’t try to build it a second time. So the command I actually ran was this (maybe this doesn’t work? It does seem to find the flake ok though):

nix flake show ihp-alternative/

Ok, I’ve taken another tack. I can see while direnv is building pandoc that it’s building doclayout-, so I found a nix store path for that package:

ls /nix/store | rg doclayout-

One of the results from that (the only one without a suffix of some kind) was wsp5zmdyszavqha49cy6qm57ps356xjz-doclayout-, so I checked if that’s in the digitally induced cache following instructions on the nixos wiki:


This gave me a 404.

But, I don’t have a lot of certainty that this is a conclusive answer: how do I know I’m checking for the right store path? Also, it seems more relevant for the top-level dependencies (pandoc, in this case) rather than the transitive dependencies.

Once pandoc has finished building I’ll try using that.

I suppose I could also check the store path for the version of ghc that’s installed when I’m in the repository. (Do those vary according to the packages you have installed, though? I.e. now that I’ve installed pandoc will that be a different hash that wouldn’t be in the cache anyway?)

I realised that my cache check was slightly incorrect: I should only be using the hash part of the store path, not the package as well:


However, this still gives me a 404.

I figured I’d check for something more normal in the cache to try and see a cache hit – maybe GHC?

Unfortunately the versions of ghc I have in my nix store appear not to be in the cache:

Emily@Peach /n/v/l/n/drvs> ls /nix/store/ | rg "ghc-[0-9.]*\$"
Emily@Peach /n/v/l/n/drvs> curl
404 - Not Found
Emily@Peach /n/v/l/n/drvs> curl
404 - Not Found
Emily@Peach /n/v/l/n/drvs> curl
404 - Not Found   

The other approach mentioned on the nixos wiki is using nix path-info, so I tried that:

Emily@Peach /n/v/l/n/drvs> nix path-info -r /nix/store/p07zdrglgsl584y4ii7cg4flinwmlzr7-ghc-9.8.2 --store
these 37 paths will be fetched (350.03 MiB download, 2884.03 MiB unpacked):
error: path '/nix/store/p07zdrglgsl584y4ii7cg4flinwmlzr7-ghc-9.8.2' is not valid

This gives me something new at least: the warning about the path not being valid.

I remember seeing this in the cachix FAQs:

I get InvalidPath error from Nix when invoking Cachix

There are two cases under which the error is raised:

  • Garbage Collection kicks in while Cachix is trying to push a path. To confirm if that’s the case, check if GC timestamps correlate with when the error was raised

  • Store paths weren’t built yet. Some Nix commands return store paths that would exist if Nix has built them.

This store path definitely exists (or at least, it does in my local nix store – is that what that means?), so I’m guessing the other bullet point is the relevant one. But… I thought nix garbage collection only runs when you manually run nix-collect-garbage? I haven’t run that today. I also don’t know where to check for GC timestamps.

Pandoc has finished building! Querying the digitallyinduced cache for the resulting store path gives a slightly different result from before:

Emily@Peach ~/W/P/ihp-alternative (main)> ls /nix/store/ | rg "pandoc-[0-9.]*\$"

Emily@Peach /n/v/l/n/drvs [1]> nix path-info -r /nix/store/jz25z7k6gz6kgl41fxnzp3la8v78v9y9-pandoc- --store
don't know how to build these paths:
error: path '/nix/store/jz25z7k6gz6kgl41fxnzp3la8v78v9y9-pandoc-' is not valid

Emily@Peach /n/v/l/n/drvs [1]> curl
404 - Not Found

I’m not sure what to make of this!

It sounds like maybe cachix isn’t being used - so it builds all the packages.

What do you get when you execute the script from here

curl --silent | python3

Ah, thanks for the suggestion! Here’s the output:

Emily@Peach ~/W/P/ihp-alternative (main)> curl --silent | python3
Checking that the current directory is an IHP project:
+ Found Main.hs
+ Found start script
+ Installed Nix version 2.21.2 is 2.4 or later
Checking direnv:
+ Found .envrc
+ direnv loads .envrc
- direnv denied .envrc, run `direnv allow` to allow .envrc
+ ghci is loaded from nix store
Checking .ghci:
+ Found .ghci
+ .ghci permissions are ok
Checking IHP:
- Symlink build/ihp-lib is missing. Try 'make build/ihp-lib' to fix this
- Symlink build/ihp-lib target directory does not exist. Try `nix-shell --run "make -B build/ihp-lib"` to fix this
+ IHP used from nix
Checking Cachix:
+ Cachix exists
+ configured
+ No legacy cachix key found
Checking IHP files:
- The file `Makefile` was edited manually.
  Try reverting your changes to to see whether that affects the issue
Debugging Details:
GHCI Output:
GHCi, version 9.8.2:  :? for help
package flags have changed, resetting and loading new packages...
package flags have changed, resetting and loading new packages...
[ 1 of 30] Compiling Application.Helper.Controller ( Application/Helper/Controller.hs, interpreted )
[ 2 of 30] Compiling Application.Helper.View ( Application/Helper/View.hs, interpreted )
[ 3 of 30] Compiling Config           ( Config/Config.hs, interpreted )
[ 4 of 30] Compiling Generated.Enums  ( build/Generated/Enums.hs, interpreted )
[ 5 of 30] Compiling Generated.ActualTypes ( build/Generated/ActualTypes.hs, interpreted )
[ 6 of 30] Compiling Generated.Event  ( build/Generated/Event.hs, interpreted )
[ 7 of 30] Compiling Generated.Types  ( build/Generated/Types.hs, interpreted )
[ 8 of 30] Compiling Admin.Types      ( Admin/Types.hs, interpreted )
[ 9 of 30] Compiling Admin.Routes     ( Admin/Routes.hs, interpreted )
[10 of 30] Compiling Admin.View.Layout ( Admin/View/Layout.hs, interpreted )
[11 of 30] Compiling Admin.View.Prelude ( Admin/View/Prelude.hs, interpreted )
[12 of 30] Compiling Admin.View.Static.Welcome ( Admin/View/Static/Welcome.hs, interpreted )
[13 of 30] Compiling Admin.Controller.Prelude ( Admin/Controller/Prelude.hs, interpreted )
[14 of 30] Compiling Admin.Controller.Static ( Admin/Controller/Static.hs, interpreted )
[15 of 30] Compiling Admin.FrontController ( Admin/FrontController.hs, interpreted )
[16 of 30] Compiling Web.Types        ( Web/Types.hs, interpreted )
[17 of 30] Compiling Web.Routes       ( Web/Routes.hs, interpreted )
[18 of 30] Compiling Web.Controller.Prelude ( Web/Controller/Prelude.hs, interpreted )
[19 of 30] Compiling Web.View.Layout  ( Web/View/Layout.hs, interpreted )
[20 of 30] Compiling Web.View.Prelude ( Web/View/Prelude.hs, interpreted )
[21 of 30] Compiling Web.View.Events.Show ( Web/View/Events/Show.hs, interpreted )
[22 of 30] Compiling Web.View.Events.New ( Web/View/Events/New.hs, interpreted )
[23 of 30] Compiling Web.View.Events.Index ( Web/View/Events/Index.hs, interpreted )
[24 of 30] Compiling Web.View.Events.Edit ( Web/View/Events/Edit.hs, interpreted )
[26 of 30] Compiling Web.View.Static.Welcome ( Web/View/Static/Welcome.hs, interpreted )
[27 of 30] Compiling Web.Controller.Static ( Web/Controller/Static.hs, interpreted )
Failed, 25 modules loaded.
Loaded GHCi configuration from /Users/Emily/Work/Pannal Village Hall (no git)/ihp-alternative/.ghci
IHP> ok
IHP> Leaving GHCi.

build/ihp-lib Target:
Direnv Output:
direnv exec path /Users/Emily/.nix-profile/bin/direnv
DIRENV_CONFIG /Users/Emily/.config/direnv
bash_path /nix/store/386xmpmnix11qhnn2l0f7lvv0dc70w8h-bash-5.2p26/bin/bash
disable_stdin false
warn_timeout 5s
whitelist.prefix []
whitelist.exact map[]
Loaded RC path /Users/Emily/Work/Pannal Village Hall (no git)/ihp-alternative/.envrc
Loaded watch: ".envrc" - 2024-06-15T14:42:51+01:00
Loaded watch: "../../../.local/share/direnv/allow/5734ee1efeb47251f6f407fbd25c1720c7f5d5c43cf6cf12844a416403143c31" - 2024-06-15T16:01:42+01:00
Loaded watch: "../../../.local/share/direnv/deny/00a4e16ffb4f24d4580bc3036b67ded88f550992f7845741c60efca9ed9c4069" - 1970-01-01T01:00:00+01:00
Loaded watch: "../../../.direnvrc" - 1970-01-01T01:00:00+01:00
Loaded watch: "../../../.config/direnv/direnvrc" - 1970-01-01T01:00:00+01:00
Loaded watch: "flake.nix" - 2024-06-16T11:49:07+01:00
Loaded watch: "flake.lock" - 2024-06-15T14:42:51+01:00
Loaded watch: "devshell.toml" - 1970-01-01T01:00:00+01:00
Loaded RC allowed 0
Loaded RC allowPath /Users/Emily/.local/share/direnv/allow/5734ee1efeb47251f6f407fbd25c1720c7f5d5c43cf6cf12844a416403143c31
Found RC path /Users/Emily/Work/Pannal Village Hall (no git)/ihp-alternative/.envrc
Found watch: ".envrc" - 2024-06-15T14:42:51+01:00
Found watch: "../../../.local/share/direnv/allow/5734ee1efeb47251f6f407fbd25c1720c7f5d5c43cf6cf12844a416403143c31" - 2024-06-15T16:01:42+01:00
Found watch: "../../../.local/share/direnv/deny/00a4e16ffb4f24d4580bc3036b67ded88f550992f7845741c60efca9ed9c4069" - 1970-01-01T01:00:00+01:00
Found RC allowed 0
Found RC allowPath /Users/Emily/.local/share/direnv/allow/5734ee1efeb47251f6f407fbd25c1720c7f5d5c43cf6cf12844a416403143c31

which direnv Output:

# For backwards compatibility using flake.nix
        fetchTarball {
            url = "";


I’m surprised that it says direnv denied .envrc, when it looks like that’s working? I have run direnv allow already, and running it again doesn’t change anything.

The Makefile edits were me adding some quotes to fix a couple of the commands to work in directories with spaces in their names:

commit f594137bb4bdaacc50b674c42ebb8a5974377fa3

diff --git a/Makefile b/Makefile
index a8624f1..a503354 100644
--- a/Makefile
+++ b/Makefile
@@ -17,3 +17,7 @@ include ${IHP}/Makefile.dist
 psql-fixed: ## Connects to the running postgresql server
        @psql -h "$$PWD"/build/db -d app
+dumpdb-fixed: dump_db-fixed ## Saves the current database state into the Fixtures.sql
+dump_db-fixed: ## Saves the current database state into the Fixtures.sql
+       pg_dump -a --inserts --column-inserts --disable-triggers -h "$$PWD"/build/db app | sed -e '/^--/d' > Application/Fixtures.sql

commit d4eb017c76056e5e862925d9d24878e6ac46f96d

diff --git a/Makefile b/Makefile
index 96fd66b..a8624f1 100644
--- a/Makefile
+++ b/Makefile
@@ -15,3 +15,5 @@ JS_FILES += ${IHP}/static/vendor/turbolinksMorphdom.js
 include ${IHP}/Makefile.dist
+psql-fixed: ## Connects to the running postgresql server
+       @psql -h "$$PWD"/build/db -d app

It was the same before this, so I doubt this has any impact.

I’ll try running that make build/ihp-lib command and see if that changes anything.

Hmmm, it doesn’t look like that’s a valid rule name?

Emily@Peach ~/W/P/ihp-alternative (main)> make build/ihp-lib
make: *** No rule to make target 'build/ihp-lib'.  Stop.

build/ihp-lib has been removed in recent IHP versions. So that’s okay. (We should likely remove it from the troubleshoot process).

I’ve recently added a patch to the GHC that is used by IHP (macOS only). This triggered a rebuild of GHC on our CI system. This could have lead to a lot of binaries being pushed to cachix, which could have caused a garbage collection of older IHP builds.

Are you running v1.3 or latest master?

Ah ok, that could be it! I think I’m using v1.3: inputs.ihp.url in flake.nix is github:digitallyinduced/ihp/v1.3. So changing to latest master and then seeing if the binary cache works would validate this theory, right?

Yes that’s a good way to test it :+1: