How to `builtins.readDir` a derivations's subdir when the subdir's path contains a symlink to another derivation's directory?

With flakes running in pure mode, builtins.readDir "${pkg}/some/path" fails when any path component of "${pkg}/some/path" is a symlink to a real directory from another derivation. Can I get around this without disabling purity or overriding builds?

The error is: error: access to canonical path '/nix/store/1ql470vbl559rihw7skn5557j66759dq-emacs-28.2/share/applications' is forbidden in restricted mode


More context:

I want to do this to refer to the desktop files of a derivation dynamically in nix, I am trying to builtins.readDir "${pkg}/share/applications" (where pkg.pname == "emacs-with-packages" ).

This has worked fine for all my other pkgs. E.g. pkgs.alacritty, which contains the file "${pkg}/share/applications/Alacritty.desktop" (and "${pkg}/share/applications" is not a symlink).

I’ve isolated the cause: in emacs-with-packages , the "${pkg}/share/applications" directory is a symlink to emacs 's ${pkg}/share/applications , source is here: https://github.com/NixOS/nixpkgs/blob/32e7d3f420607c2d7f9fe66fdd945a2f95c7fded/pkgs/build-support/emacs/wrapper.nix#L225 (edited)

I don’t have an answer to your question, but just wanted to point out that reading a derivation result from nix like this is IFD, and generally frowned upon, for a few reasons:

  • Nix handles IFD very poorly, causing it to start eval from scratch every time it encounters it. This means nix evaluation takes O(n^2) time in the number of IFD instances.
  • Hydra cannot handle IFD at all.
  • It prevents certain useful processes from working, such as instantiating but not building, and then walking the produced tree of .drvs to list all the FODs.

Try not to do this if you can avoid it.

That said, this sounds like a bug in nix. It really should include the whole closure of the package in the allowed paths when you do use IFD.

1 Like

Thank you, indeed my evaluation has been very slow (~25s). I’ll try removing these IFDs and that causes a sub-5-second eval, your answer will have helped me more than the intended answer.

I did it, and interestingly, my evaluation time actually went up by 5 seconds. I suspect

Nix handles IFD very poorly, causing it to start eval from scratch every time it encounters it.

may have had improvements in recent nix versions and is no longer true. At any rate, since there is too little documentation around IFD for my liking, I have chosen to keep the change and am avoiding it.

Yeah this doesn’t sound right. IFD can indeed be slow, but I can’t see why it would be O(n^2).

There is some documentation for IFD being worked on recently: Document "Import From Derivation" by fricklerhandwerk · Pull Request #7332 · NixOS/nix · GitHub

1 Like

Hmm. Well that was my understanding from some time back. It may have changed, or I might never have been right about it to begin with. The doc does say evaluation is “resumed”, rather than “restarted”, though I wouldn’t count on that level of nuance in wording. Probably the only way to be sure is to actually check the code.