Infinite recursion when importing nix-flatpak in configuration.nix

Basically what the title says. This seems to be an ongoing issue with some nix projects; the maintainer for nix-pkgs warns about this issue. But apparently this only applies if either using flakes, or if importing the nix-flatpak home-manager module from a file other than configuration.nix, neither of which I am doing. This is how I import it:

configuration.nix

{ config, lib, pkgs, ... }:
with import ./sys_variables.nix; {
  imports = let
    home-manager = builtins.fetchTarball {
      url = "https://github.com/nix-community/home-manager/archive/release-${nix_current_ver}.tar.gz";
      sha256 = "07pk5m6mxi666dclaxdwf7xrinifv01vvgxn49bjr8rsbh31syaq";
    };
    nix-flatpak = pkgs.fetchFromGitHub {
      owner = "gmodena";
      repo = "nix-flatpak";
      rev = "v0.6.0";
      hash = "sha256-iAVVHi7X3kWORftY+LVbRiStRnQEob2TULWyjMS6dWg=";
    };
  in [
    ./hardware-configuration.nix # Include the results of the hardware scan.
    (import "${home-manager}/nixos")
    "${nix-flatpak}/modules/nixos.nix"
    # "${nix-flatpak}/modules/home-manager.nix"
    # nixvim.homeManagerModules.nixvim
  ];
}

I am also aware of these two posts here and here. Apparently the fix is to add nix-flatpak to extraSpecialArgs, but that’s a flake component, and I’m not using flakes. Is there an equivalent option for a normal nix configuration?

Your imports depends on pkgs, you’ll have to use a builtin to fetch most likely. But share the actual error anyway, ā€œinfinite recursionā€ is too vague.

Also, the way you’re fetching home-manager is also incorrect, you’re trying to hash a tarball that will always change - instead you’d have to pin to a commit and update it as needed (using npins would be a much easier way to do this automatically). You could then use npins for the nix-flatpak as well.

1 Like

So yeah using builtins.fetchGit helped, I can even import it both in configuration.nix and home.nix without a problem.

I wasn’t gonna post the full error because it’s kinda long and I thought it was the same error as in the flakes case (but actually it wasn’t), but here it is anyway:

error:
       … while evaluating the attribute 'config'
         at /nix/store/5g5w8xjrzxvrqn6v2si0z82h7ydx8pk0-nixos-25.05.812955.c58bc7f54593/nixos/lib/modules.nix:359:9:
          358|         options = checked options;
          359|         config = checked (removeAttrs config [ "_module" ]);
             |         ^
          360|         _module = checked (config._module);

       … while calling the 'seq' builtin
         at /nix/store/5g5w8xjrzxvrqn6v2si0z82h7ydx8pk0-nixos-25.05.812955.c58bc7f54593/nixos/lib/modules.nix:359:18:
          358|         options = checked options;
          359|         config = checked (removeAttrs config [ "_module" ]);
             |                  ^
          360|         _module = checked (config._module);

       … while evaluating the module argument `pkgs' in "/etc/nixos/configuration.nix":

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

       error: infinite recursion encountered
       at /nix/store/5g5w8xjrzxvrqn6v2si0z82h7ydx8pk0-nixos-25.05.812955.c58bc7f54593/nixos/lib/modules.nix:652:66:
          651|       extraArgs = mapAttrs (
          652|         name: _: addErrorContext (context name) (args.${name} or config._module.args.${name})
             |                                                                  ^
          653|       ) (functionArgs f);
building Nix...
error:
       … while evaluating the attribute 'config'
         at /nix/store/5g5w8xjrzxvrqn6v2si0z82h7ydx8pk0-nixos-25.05.812955.c58bc7f54593/nixos/lib/modules.nix:359:9:
          358|         options = checked options;
          359|         config = checked (removeAttrs config [ "_module" ]);
             |         ^
          360|         _module = checked (config._module);

       … while calling the 'seq' builtin
         at /nix/store/5g5w8xjrzxvrqn6v2si0z82h7ydx8pk0-nixos-25.05.812955.c58bc7f54593/nixos/lib/modules.nix:359:18:
          358|         options = checked options;
          359|         config = checked (removeAttrs config [ "_module" ]);
             |                  ^
          360|         _module = checked (config._module);

       … while evaluating the module argument `pkgs' in "/etc/nixos/configuration.nix":

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

       error: infinite recursion encountered
       at /nix/store/5g5w8xjrzxvrqn6v2si0z82h7ydx8pk0-nixos-25.05.812955.c58bc7f54593/nixos/lib/modules.nix:652:66:
          651|       extraArgs = mapAttrs (
          652|         name: _: addErrorContext (context name) (args.${name} or config._module.args.${name})
             |                                                                  ^
          653|       ) (functionArgs f);
building the system configuration...
error:
       … while evaluating the attribute 'config.system.build.toplevel'
         at /nix/store/5g5w8xjrzxvrqn6v2si0z82h7ydx8pk0-nixos-25.05.812955.c58bc7f54593/nixos/lib/modules.nix:359:9:
          358|         options = checked options;
          359|         config = checked (removeAttrs config [ "_module" ]);
             |         ^
          360|         _module = checked (config._module);

       … while calling the 'seq' builtin
         at /nix/store/5g5w8xjrzxvrqn6v2si0z82h7ydx8pk0-nixos-25.05.812955.c58bc7f54593/nixos/lib/modules.nix:359:18:
          358|         options = checked options;
          359|         config = checked (removeAttrs config [ "_module" ]);
             |                  ^
          360|         _module = checked (config._module);

       … while evaluating the module argument `pkgs' in "/etc/nixos/configuration.nix":

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

       error: infinite recursion encountered
       at /nix/store/5g5w8xjrzxvrqn6v2si0z82h7ydx8pk0-nixos-25.05.812955.c58bc7f54593/nixos/lib/modules.nix:652:66:
          651|       extraArgs = mapAttrs (
          652|         name: _: addErrorContext (context name) (args.${name} or config._module.args.${name})
             |                                                                  ^
          653|       ) (functionArgs f);

As for npins, I tried to import home-manager with it, but it seems like more of a headache than a helpful tool. It seems that I can’t import home manager the way that is described in the home manager doc, but at the same time npins doesn’t make it clear how to do it either. I think its best I just stay away from it for now.

{ config, lib, pkgs, ... }:
let
  sources = import ./npins;
in
 {
  imports = [
    ./hardware-configuration.nix 
    (sources.home-manager + "/nixos")
    (sources.nix-flatpak + "/modules/nixos.nix")
  ];

  # etc.
}

EDIT: fixed typo

huh… I definately did not have a sources.nix. The only files I get are default.nix and sources.json. Maybe that was a typo? But yeah if you replace that with default.nix thats essentially what I tried and was getting an error about some ā€œcould not coerce to a stringā€ (i forgor), which i think is because npins sources aren’t actually modules or paths

I’ll double check when I’m at a PC.

1 Like

They are paths, because that’s what the builtins.fetch* functions return. They do in fact only have a default.nix tho, see here.

It’d be nice if you could give that another shot and show your homework, @waffle8946 and I just helped someone else set up npins yesterday and it was working fine :wink:

2 Likes

They do in fact only have a default.nix tho, see here.

It’s funny how npins itself uses npins for its packages xD

So I follow the npins readme. I added npins to my packages in configuration.nix, but I also opened a nix-shell with the npins package so I didn’t have to rebuild. Then I did npins init in /etc/nixos, and it added npins/default.nix and npins/sources.nix with nixpkgs-unstable already added in it (I kinda wanna use stable packages, but I could roll with it for now). Then I added home-manager and nix-flatpak: npins add github nix-community home-manager -b release-25.11 and npins add github gmodena nix-flatpak --at v0.6.0.

This is how I import everything in configuration.nix:

{ config, lib, ... }:
let
  npins = import ./npins;
  pkgs = import npins.nixpkgs {};
in with import ./sys_variables.nix; {
  imports = [
    ./hardware-configuration.nix # Include the results of the hardware scan.
    ./locale.nix
    "${npins.home-manager}/nixos"
    "${npins.nix-flatpak}/modules/nixos.nix"
  ];
}

Unsurprisingly :slight_smile: I get a different error now:

error:
       … while calling the 'head' builtin
         at /nix/store/f3qxxqkp3z2nbr2r16gdw95ynaqla7zn-nixos-25.11/nixos/lib/attrsets.nix:1696:13:
         1695|           if length values == 1 || pred here (elemAt values 1) (head values) then
         1696|             head values
             |             ^
         1697|           else

       … while evaluating the attribute 'value'
         at /nix/store/f3qxxqkp3z2nbr2r16gdw95ynaqla7zn-nixos-25.11/nixos/lib/modules.nix:1118:7:
         1117|     // {
         1118|       value = addErrorContext "while evaluating the option `${showOption loc}':" value;
             |       ^
         1119|       inherit (res.defsFinal') highestPrio;

       … while evaluating the option `system.build.toplevel':

       … while evaluating definitions from `/nix/store/f3qxxqkp3z2nbr2r16gdw95ynaqla7zn-nixos-25.11/nixos/nixos/modules/system/activation/top-level.nix':

       … while evaluating the option `system.systemBuilderArgs':

       … while evaluating definitions from `/nix/store/f3qxxqkp3z2nbr2r16gdw95ynaqla7zn-nixos-25.11/nixos/nixos/modules/system/activation/activatable-system.nix':

       … while evaluating the option `system.activationScripts.etc.text':

       … while evaluating definitions from `/nix/store/f3qxxqkp3z2nbr2r16gdw95ynaqla7zn-nixos-25.11/nixos/nixos/modules/system/etc/etc-activation.nix':

       … while evaluating definitions from `/nix/store/f3qxxqkp3z2nbr2r16gdw95ynaqla7zn-nixos-25.11/nixos/nixos/modules/system/etc/etc.nix':

       … while evaluating the option `environment.etc.dbus-1.source':

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

       error: A definition for option `environment.systemPackages."[definition 1-entry 1]"' is not of type `package'. Definition values:
       - In `/etc/nixos/configuration.nix':
           {
             home-manager = {
               branch = "release-25.11";
               hash = "04wrwfwhiwx2rylr74gha0p4g3ly9slgcc7nbs9gzdxw7mmzvpig";
               outPath = "/nix/store/ba5f1y10pw9zqjqhklbri88p0p523qhw-source";
           ...
Command 'nix-build '<nixpkgs/nixos>' --attr config.system.build.toplevel --no-out-link' returned non-zero exit status 1.

Looks like npins can’t import home manager, not sure why tho.

Thanks again for the help @TLATER .

I think for home manager you need to do

  imports =
    [
      (import "${npins.home-manager}/nixos")
    ];

See: https://nix-community.github.io/home-manager/index.xhtml#sec-install-nixos-module

1 Like

I appreciate the docs link (and maybe the docs need discussion too), but why would the import do anything here? There’s no args applied and nixos/default.nix is already a module. Also it doesn’t square with their error. IMO import should not be used at all.

@Megadash452 Did you add something to environment.systemPackages? From the error it looks like you added npins.home-manager (which, as the error says, is not a package) to environment.systemPackages; it should be removed. Using hm as a NixOS module requires no additional packages.

This code also seems… off - what is sys_variables.nix and why is it not a module? Using import in the module system is an anti-pattern, it will cause hard-to-debug issues and even obscures the file location in errors.

1 Like

I tried it both with and without import. I got something different when using import, but i forgor what the erorr was.

The only thing i added to environment.systemPackages is the npins package, I did not add home manager in there.

environment.systemPackages = with pkgs; [ npins ];

The code also seems… off

lolll yea, sysvariables.nix is just an attribute set containing values (e.g. my user name, nix state version, etc.) that I don’t wanna copy throughout my entire config tree, so I just created to variables in that file and import it wherever I need them. I don’t know if there’s a better way to do this, but thats what i came up with at the start :man_shrugging:

Verbatim sys_variables.nix

{
  admin_user = "marti";
  host_name = "nixos";
  nix_current_ver = "25.11";
  # Base install version. Must match ISO version. Do not change. 
  nix_iso_ver = "25.05"; # Do not change.
}

There’s the problem. That should be

environment.systemPackages = [ pkgs.npins ];

with does not do what you think it does.
In your current code it’s using the existing in-scope npins binding which you have set to import ./npins, not pkgs.npins. So your code is basically

# wrong
environment.systemPackages = [ npins ];
# equivalent(ly wrong)
environment.systemPackages = [ (import ./npins) ];

https://nix.dev/manual/nix/2.32/language/syntax#with-expressions

The bindings introduced by with do not shadow bindings introduced by other means

with-exprs are the cause of so many avoidable errors that I question its convenience - the more explicit inherit-style exprs or even just typing it out seem to work better for avoiding such errors.

3 Likes

Bruuuh… Yeah that’s crazy. I think that’s why in all the examples I’ve seen they make the variable sources instead of npins.

Man ngl, nix language is not very good. the syntax is weird in a lot of areas, the utilities are weird too, and the error messages are attrociously bad. I feel like the learning curve for nix is so steep mostly because of the language itself. This language is in need of a rewrite, don’t you agree?

The language is actually fine IMO. I get the syntax and working inside fixed-point functions being unusual to someone coming from an imperative programming background, but that’s just getting used to functional programming; IMO nix writes much nicer for the purpose it’s designed for than something like C, JS/TS or python would. It’d anyway be very hard to get this kind of module/massive package system out of an imperative language with anything resembling ok performance, let alone with the ergonomics the NixOS module system has. You’re likely still overlooking a lot of the expressiveness it actually gives you.

There are things like removing with and such that could help if you’re not very experienced, but those are minor nits that can be solved just as adequately with a linter or an anti-pattern guide, and aren’t any worse in the hands of a newbie than the misfeatures other languages have (e.g. C macros, python’s GIL, JS’ type autocasting, TS’ any type …).

The error messages here definitely don’t tell you what to do, and that’s a problem. These are NixOS error messages, though, and those are so atrocious because NixOS is a deployment system implemented in nix, which means it has no control over language features, like types or introspection, that could deliver better messages. Providing something better would require NixOS-specific extensions to nix and the language (which are tricky to do in a performant way), not really a redesign of the language itself.

If anything we need better, and importantly more centralized tooling. Nix isn’t currently a language you can learn by flinging crap at your compiler until it produces something, and unfortunately that’s the mode most people are in when they learn a new language/ecosystem. There is tooling that helps with this, but a lot of it is in its infancy - there’s for example statix, nil, nixd, various formatters, deadnix, etc., which would all help you build intuition faster, but they’re all third party projects and you have to go out of your way to discover and use them (and at least statix - which I’d consider perhaps the most important - is practically unmaintained, so kinda useless in practice, even if nil picks up some slack).

Part of it is also that newbies are often newbies not just to nix, but to writing software in general (as many come from a sysadmin, or not even a software-related background at all, or are very green), so we have a lot of folk trying to program in nano - a far cry removed from figuring out how to use ecosystem tooling by themselves.

Sure, but I’m not willing to spend years doing that :grin:
I use nix to save time, not do extra work - and the language is good-enough for my purposes since I avoid stuff like with.

I also tend to prefix local bindings with _ to avoid accidental shadowing.

1 Like

I think mispoke when I said syntax. The paradigm is fine, and I actually like the declarative syntax of nix and find it much easier to write concisely than with an imperative language. What I meant was like the way things interact in the language is inconsistent. The name shadowing is an example. Another is the pkgs.FetchFromGithub and variants that they don’t behave as one would expect them to (I’m still not sure why it’s not in builtins and it behaves differently from FetchGit).

One problem I do have with the syntax tho is that lists don’t use commas, and that causes ambiguity when calling functions, so parenthesis are put around the whole thing. But that’s not really a major problem, just a gripe.

can be solved just as adequately with a linter

Now that you mention it, an LSP with documentation and schemas would be nice :thinking: I’ll look into that.

I find it interesting and horryfying that nixos itself is implemented in a declarative language meant for package and file management :fearful: Definitely a bad design decision. Sure this could not be fixed by rewriting the nix language, but deployment system maybe should be implemented in an imperative language (yk what they say about rewriting it in rust :wink:).

flinging crap at your compiler until it produces something

lmaooo literally how I learned rust :skull::skull::skull::skull:

If anything we need better, and importantly more centralized tooling

Yeah definitely. Imo one of the most important aspects of a language is the tooling. Same with the documentation, which I also find very lacking with nix, which you mentioned before is because of the decentralization.

so we have a lot of folk trying to program in nano

I see your point, but at the same time I think it shouldn’t matter if you’re writing something like nix in microsoft word :face_with_hand_over_mouth:. Sure it’s gonna be more time consuming and you’re gonna miss a lot of semicolons. But it’s the official doc pages and how they link to external common tooling and the tooling documentation that make people learn.

1 Like

Unfortunately nix error messaging is not nearly as good as rustc. Though it’s improving incrementally.

The nix code is orchestrating the merging of config and building the relevant derivations, but the deployment is done via a mishmash of

  • bash (every builder in nixpkgs is using bash underneath)
  • perl (environment.etc stuff, user/group stuff)
  • python (nixos-rebuild-ng, systemd-boot-builder.py)
  • rust (switch-to-configuration-ng)
  • cue (bootspec.cue)

and perhaps others.

1 Like

So I tried it again, this time removing every with clause and using pkgs.. But now I can’t install unfree packages. I have a list of allowed unfree packages in my configuration.nix, and I also tried with the environment variable NIXPKGS_ALLOW_UNFREE=1 , but nixos-rebuild doesn’t seem to recognize that they are activated. Google doesn’t seem to have anything either :man_shrugging:

error: Package ā€˜android-studio-stable-2025.2.1.8’ in /nix/store/1vk95i1wh5ln6fbd3nz20slmvip2xmr1-source/pkgs/applications/editors/android-studio/common.nix:306 has an unfree license (ā€˜asl20 unfree’), refusing to evaluate.

       a) To temporarily allow unfree packages, you can use an environment variable
          for a single invocation of the nix tools.

            $ export NIXPKGS_ALLOW_UNFREE=1

          Note: When using `nix shell`, `nix build`, `nix develop`, etc with a flake,
                then pass `--impure` in order to allow use of environment variables.

       b) For `nixos-rebuild` you can set
         { nixpkgs.config.allowUnfree = true; }
       in configuration.nix to override this.

       Alternatively you can configure a predicate to allow specific packages:
         { nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
             "android-studio-stable"
           ];
         }

       c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
         { allowUnfree = true; }
       to ~/.config/nixpkgs/config.nix.
Command 'nix-build '<nixpkgs/nixos>' --attr config.system.build.toplevel --no-out-link' returned non-zero exit status 1.

Btw, the error only shows for the first unfree package that nixos encounters. If I were to remove android-studio from environment.systemPackages the error would show for ffmpeg instead.

This issue should have nothing to do with removing with - but in any case:

Please show the code, both the allowed list of unfree packages and how you added the unfree packages to your config.

What’re the exact commands you ran?

This issue should have nothing to do with removing with

I know, just sying

Almost verbatim configuration.nix, skipping only services and networking.

{ config, lib, ... }:
let
  npins = import ./npins;
  pkgs = import npins.nixpkgs {};
  sysvars = import ./sys_variables.nix;
in {
  imports = [
    ./hardware-configuration.nix # Include the results of the hardware scan.
    ./locale.nix
    "${npins.home-manager}/nixos"
    # TODO: look into declarative flatpak instead, might be less resource intensive
    "${npins.nix-flatpak}/modules/nixos.nix"
  ];

  home-manager = {
    users = import ./home.nix;
    useGlobalPkgs = true;
    backupFileExtension = "backup";
  };
  users.users."${sysvars.admin_user}" = {
    isNormalUser = true;
    extraGroups = [ "wheel" "input" "adbusers" ];
    packages = [ ];
  };

  # List packages installed in system profile.
  # You can use https://search.nixos.org/ to find more packages (and options).
  environment.systemPackages = [
    pkgs.npins
    pkgs.kitty pkgs.neovim pkgs.git pkgs.wget pkgs.zip pkgs.unzip pkgs.tldr pkgs.xfce.thunar
    pkgs.android-studio
    (pkgs.ffmpeg-full.override { withUnfree = true; })
  ];
  programs = {
    steam.enable = true;
    firefox.enable = true;
    adb.enable = true;
    ssh = {
      startAgent = true;
      enableAskPassword = true;
    };
    neovim = {
      enable = true;
      defaultEditor = true;
      viAlias = true;
      vimAlias = true;
    };
    hyprland = {
      enable = true;
      xwayland.enable = true;
    };
  };

  # Enable portals. Required for Flatpak
  xdg.portal.extraPortals = [
    pkgs.xdg-desktop-portal-gtk
    pkgs.xdg-desktop-portal-hyprland
  ];
  xdg.portal.config.common.default = "gtk";

  nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
    "steam" "steam-unwrapped" "ffmpeg-full" "android-studio-stable" "osu-lazer-bin"
  ];

  fileSystems = {
    # Secondary hard drive
    "/mnt/sata-ssd".label = "sata-ssd";
    # Required to remove security warning
    "/boot".options = [ "umask=0077" ];
  };
  
  # Some programs need SUID wrappers, can be configured further or are started in user sessions.
  # programs.mtr.enable = true;
  # programs.gnupg.agent = {
  #   enable = true;
  #   enableSSHSupport = true;
  # };

  # Use the systemd-boot EFI boot loader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  system = {
    # Base install version. Must match ISO version. Do not change.
    stateVersion = sysvars.nix_iso_ver; # Do not change
    # Copy the NixOS configuration file and link it from the resulting system (/run/current-system/configuration.nix).
    # This is useful in case you accidentally delete configuration.nix.
    copySystemConfiguration = true;
  };
}

and this is the command I run

NIXPKGS_ALLOW_UNFREE=1 sudo nixos-rebuild switch