Infinite recursion encountered, at undefined position, with callPackage in overlays

I built my first overlay to add a font (scientifica) not found in nixpkgs. Even though the overlay is based off known-good configurations (e.g. Good examples > Add custom package), it seems to break vital Nix utilities like nix-env and nix-shell, which I use to install packages.

Troubleshooting

I looked through the top 10 Discourse threads for ‘infinite recursion’ in addition to other assorted resources, but haven’t seen or applied a measure which has fixed my problem so far. Additional troubleshooting steps are noted in “Configurations” below.

Configurations
Below is my entire overlays/scientifica/default.nix function. Building the package without adding it to nixpkgs (nix-build -E 'with import <nixpkgs> { }; callPackage ./default.nix { }') has not caused any errors.

{ stdenv, fetchzip }:

stdenv.mkDerivation rec {
  pname = "scientifica";
  version = "v2.1";
  src = fetchzip {
    url = "https://github.com/NerdyPepper/scientifica/releases/latest/download/${pname}-${version}.tar";
    sha256 = "1mji70h5qdplx0rlhijrdpbmvd0c6fvnr70sla032gfs5g6f78cn";
  };

  dontBuild = true;
  installPhase = ''
    mkdir -p $out/share/fonts/truetype/
    mkdir -p $out/share/fonts/misc/
    cp ttf/* -d $out/share/fonts/truetype/
    cp otb/* -d $out/share/fonts/misc/
    cp bdf/* -d $out/share/fonts/misc/
  '';

  # metadata
  meta = with stdenv.lib; {
    description = "Tall and condensed bitmap font for geeks";
    homepage = "https://github.com/NerdyPepper/scientifica";
    license = licenses.ofl;
    platforms = platforms.all;
  };
}

Below is the entirety of /overlays/default.nix. Commenting all lines of the overlay results in a separate, “unexpected $END” type of error. If I remove the /overlays directory and rebuild, Nix utilities work perfectly fine, so I suspect this is causing my problems.

self: super:
{
  scientifica = super.callPackage ./scientifica { };
}

Below are the relevant lines from my /desktop/fonts.nix file which imports the overlay. Removing ./ (current directory) before the overlay path fixed Nix utilities, until they spontaneously broke again. Commenting lines out has not resulted in any changes.

{ config, pkgs, ... }:

{
  nixpkgs.overlays = [
    (import ../overlays/default.nix)
  ];
  
  [...]
  
  fonts = {
    [...]
	fonts = with pkgs; [
	  scientifica
	]
  };
  
  [...]
}''

Below are the relevant lines from configuration.nix. Commenting lines out has not resulted in any changes.

{ config, pkgs, options, ... }:

{
  imports =
    [ 
      [...]
      ./desktop/fonts.nix
    ];

  [...]
  
  nix.nixPath =
    options.nix.nixPath.default ++
    [ "nixpkgs-overlays=/etc/nixos/overlays/" ]
  ;

Errors

The following issues appear when signed in to either user or root. nix-info returns the following error message. I know that system: 0, multi-user?: no are not expected values, as seen in this similar thread.

error: infinite recursion encountered, at undefined position
system: 0, multi-user?: no, version: nix-env (Nix) 2.3.9, channels(user): "nixpkgs-21.03pre257784.253de1fcdb3", channels(root): "nixos-20.09.2190.78dc359abf8, nixos-hardware", nixpkgs: /home/user/.nix-defexpr/channels/nixpkgs

nix-channels returns:

nixos https://nixos.org/channels/nixos-20.09
nixos-hardware https://github.com/NixOS/nixos-hardware/archive/master.tar.gz

nix-env -qa and nix-env -iA nixos.pipes both return:

error: infinite recursion encountered, at undefined position

nix-shell returns:

error: getting status of '/home/user/default.nix': No such file or directory

Final notes

Any help would be much appreciated.

IIRC, using rec inside of a package description is discouraged, because it can cause just this issue when used in an overlay. Try removing it, and using a let binding above the call to mkDerivation instead. Let me know if that works.

1 Like

Thanks for the quick reply!

You remember correctly: rec is documented as an anti-pattern, with some pitfalls including those gnarly infinite recursion errors.

Below are the prepended let binding and other function changes I made, based on the pname + version pattern seen here.

let
  pname = "scientifica";
  version = "v2.1";
in
stdenv.mkDerivation { 
# removing 'stdenv.' results in "undefined variable 'mkDerivation'" error
  name = "${pname}-${version}";

The new overlays/scientifica/default.nix function successfully builds with nixos-rebuild test and nixos-rebuild switch. However, all Nix utilities mentioned throw the same errors mentioned in the OP.

Bikeshed: the name = "${pname}-${version}" pattern is specifically called out as not good in the issue you linked because it doesn’t provide the pname and version directly to mkDerivation. If you want to avoid rec, it’s preferred to do something like

let
  pname = "scientifica";
  version = "2.1";
in
stdenv.mkDerivation { 
  inherit pname version;
2 Likes

I am not convinced that rec is to blame here. It certainly can cause infinite recursion, because it computes a fixed point, but I don’t see that happening here…
Can you try removing all the overlay related stuff, rebuild your system, and then add it back, but without the part about nix.nixPath, try to rebuild your system again and see if things work?

(you need to rebuild twice like that, because the NIX_PATH on first rebuild will still have the old value)

It looks to me like you import the overlay twice (although I don’t quite understand why that should cause infinite recursion either…).

3 Likes

So your saying that the infinite recursion is no longer occuring during a nixos-rebuild but is still occurs when calling nix-env -qa?

Thanks for the tip. I found an intermediate solution, name = pname; version = version;, but that looked a bit silly to me and I wasn’t alone. inherit looks far cleaner, and solves needing name declared, given initiatives toward pname.

After removing the entire overlays directory and any references, rebuilding the system, adding them back with nix.nixPath = [ options.nix.nixPath.default ];, and rebuilding two more times:

  • The overlay works as intended.
  • nix-env and nix-info also work as intended.

I initially thought to add the overlays directory based on these instructions for system level overlay application. Retrospectively, this doesn’t seem like what I needed anyhow.

I, too, don’t understand the cause of the infinite recursion - but at least my problem is solved.

Thank you for your help!

  • Infinite recursion hasn’t occurred during any of my rebuilds.
  • nix-env and nix-info threw infinite recursion errors up until I took the steps noted in my previous reply.
  • nix-shell continues to throw the same (unrelated) error and I’ll troubleshoot that separately.