Weird issue while expanding an home-manager module

I’m trying to make a way for mpv scripts to add fonts to mpv.
My idea is that mpv scripts will have passthru.fonts = ["my-font.ttf"]; (like passthru.scriptName) and the home-manager module will create a symlink for each font to ~/.config/mpv/fonts/.
For example:
~/.config/mpv/fonts/my-font.ttf will be a symlink to ${script}/share/mpv/fonts/my-font.ttf

So I tried to do that but I’ve encountered a weird error…
I’m getting error: infinite recursion encountered and I can’t figure out why.
These are the changes I’ve made Comparing nix-community:master...FlafyDev:master · nix-community/home-manager · GitHub

And if I change cfg.scripts to [{fonts = [];}] it doesn’t throw the recursion error.

This is the trace: trace · GitHub

This is a fairly common failure mode. You did your computing too close to the root of the option tree. You could have set ANY option from that mkMerge, so it has to compute at least some of the expression before it knows the values of ANY options, and since the expression depends on other options, infinite recursion.

What if you had set programs.mpv.scripts inside the mkMerge? Nix can’t tell the difference at that stage of execution, so it’s stuck.

Basically you want to do { xdg.configFile = mkMerge ...; } instead.

1 Like

Thank you so much! this solved the issue.
I still can’t understand why it resulted in infinite recursion and how the code is different now than how it was before.

Basically, nix can’t tell that you didn’t do this:

(mkMerge 
  (lists.flatten 
    (map (script: 
      (if builtins.hasAttr "fonts" script then
          (map (font: {
            xdg.configFile."mpv/fonts/${font}".source = "${script}/share/mpv/fonts/${font}";
            programs.mpv.scripts = [ (...) ];
          }) script.fonts)
        else []
      ))
      cfg.scripts
    )
  )
)

By moving the mkMerge down the tree, you narrow down what options that big hunk of computation could possibly affect (only things under xdg.configFile), and in particular, rule out the possibility of it affecting programs.mpv.scripts, which is used to create it.

1 Like

Thanks, I think I understand it a little better now!