Infinite recursion encountered, at undefined position

With the following code:

let

    nixpkgs = import <nixpkgs> {
        overlays = import ./overlays;
        config = {
            packageOverrides = pkgs: {
                haskellPackages = pkgs.haskellPackages.override {
                    overrides = self: super: {
                        order-processor = super.callCabal2nix "order-processor" ../code/order-processor {};
                    };
                };
            };
        };
    };

    make-test = import <nixpkgs/nixos/tests/make-test.nix>;

    post-order = nixpkgs.fcbScript { pattern = "curl"; path = ../docs/QUICKSTART.md; };

in

    make-test {
...

when I try to run the test, I get an infinite recursion error:

nix-build ./test-quickstart.nix
error: infinite recursion encountered, at undefined position
(use '--show-trace' to show detailed location information)

--show-trace doesn’t really help.

Both

  1. removing the test and just building the haskell package and
  2. removing the haskell package and just generating the post-order script seem to work fine.

the moment I try to combine the two I get the infinite recursion.

I have no idea what it might be caused by.
Any help is appreciated.

Out of curiosity, why are you using both overlays and packageOverrides? The latter is generally obsoleted by the former.

For some reason I was of the impression that overlays are a way to redistribute reusable “patches” to nixpkgs and packageOverrides are better for project specific changes.

I now realise this is not really based on anything I’ve read. Is this “obsoletion” documented anywhere?

To clarify: the overlays above are used only to reference remote repositories in this case https://github.com/fghibellini/nix-markdown-snippets which provides the fcbScript function, whereas all the rest is local nix code

Holy moly! https://twitter.com/search?q=infinite+recursion+encountered
Doesn’t look good

Could you try using nixpkgs.nixosTest instead of make-test = import <nixpkgs/nixos/tests/make-test.nix>?

I tried to call nixosTest with the same arguments and it threw the same error

I found it. You forgot parentheses in overlays/default.nix. So it should be:

[
    (import ./nix-markdown-snippets.nix)
]

Why this lead to infinite recursion I leave as an exercise for the reader :wink:

I’m surprised that didn’t trigger error: cannot coerce a set to a string when trying to actually invoke the import “overlay”.

I don’t think this is documented properly, no. But packageOverrides is literally implemented as an overlay that throws away the self argument and only passes super to the defined function. And from what I’ve read overlays was intended to obsolete packageOverrides. I wish someone would update the manual where it talks about packageOverrides though.

Thanks a lot, definitely owe you a beer for this one!

Also (just for statistics) it’s not exactly the first error that would have been prevented by types that I have encountered recently.

2 Likes

I would really appreciate an explanation to this phenomenon as I can’t understand what are the semantics when the overlay list has 2 items “import” and “./nix-markdown-snippets.nix” and how does it cause the aforementioned infinite recursion problem.

Even just a hint would be greatly appreciated :slight_smile:

The overlay array is an array of functions that take self: super:. By including import as the function directly, this is calling import self, and using that as part of the definition of self. import appears to call builtins.toPath on its argument, which in turn calls toString (and then interprets the results as an absolute path). toString can accept a set, if the set contains a __toString = self: … attribute.

So, as a result, if an entry in the overlays attribute is the function import, it tries to evaluate import self, where self is a set, and the import ends up forcing the __toString attribute, and in order to determine if there is in fact a __toString attribute it needs to evaluate the overlays, which ends up recursing right back to the import.

3 Likes

Thanks @lilyball For the answer!

It didn’t occur to me to treat import as just a normal function that accepts self and super arguments, although that is precisely the would-be type for the args of the overlays array, makes sense now, thanks (again) for that!