Infinite recursion in homemanager

I’m relatively new to nix and I wanted to implement a conditional configuration.
certain imports/packages would be only added if the DISPLAY environment variable was present.

I started in my home.nix:

  { config, lib, pkgs, ... }:                                                                                                                                                                                                                          
    guicheck = builtins.readFile (pkgs.runCommand "guicheck" {} ''    
      if [ -n "$DISPLAY" ] || [ -n "$WAYLAND_DISPLAY" ]; then    
        echo 1 > $out    
        echo 0 > $out    
    imports = [    
    ] ++ (if (config.gui.enabled) then [    
      ] else []);     
    options = {    
      gui.enabled = lib.mkOption {     
        type = lib.types.bool;    
        default = false;    
    config = {                                                                                                                                                                                                                                         
      gui.enabled = (if (guicheck == "1") then true else false);                                                                                                                                                                                     
      home.username = "kyle";                                                                                                                                                                                                                          
      home.homeDirectory = "/home/kyle";                                                                                                                                                                                                               
      home.stateVersion = "24.05";                                                                                                                                                                                                                     
      programs.git = {    
        enable = true;                                                                                                                                                                                                                                 
        userName = "kyle";                                                                                                                                                                                                                             
        userEmail = "";                                                                                                                                                                                                          

This configuration ends up with:

       … while evaluating a branch condition

         at /nix/store/z71lmgd0ydfnax1b13zbrls5idf1y7ak-source/lib/lists.nix:125:9:

          124|       fold' = n:
          125|         if n == len
             |         ^
          126|         then nul

       … while calling the 'length' builtin

         at /nix/store/z71lmgd0ydfnax1b13zbrls5idf1y7ak-source/lib/lists.nix:123:13:

          122|     let
          123|       len = length list;
             |             ^
          124|       fold' = n:

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

       error: infinite recursion encountered

       at /nix/store/z71lmgd0ydfnax1b13zbrls5idf1y7ak-source/lib/modules.nix:233:21:

          232|           (regularModules ++ [ internalModule ])
          233|           ({ inherit lib options config specialArgs; } // specialArgs);
             |                     ^
          234|         in mergeModules prefix (reverseList collected);

This seems to happen when I add the if condition to the imports list

Yup, your import list can’t depend on config, because config is computed after all the modules are imported. Think of imports as like #include directives in C files—you need to have all of them even if you don’t end up using them at run time.

You should make your imports unconditional and make the things that you’re importing enable themselves based on config values, if you want to do things that way.


If you want to check an environmental variable, there is a function for that. However it is impure and I don’t recommend doing it this way. You should have a bool option which is set for your device’s specific config instead of conditionally on an environmental variable.

My home-manager config is separated from nixos.
I plan to use my flake on both nixos and non-nixos systems.
because of that I’m not able to check services.xserver.enable in home-manager

I don’t mind doing impure things. I just need to keep tabs on what is impure.
If you have a pure method to have home-manager (standalone) know if I have a displaymanager/xserver/wayland/etc I’m all ears.

I found another way to do it.
it’s not pretty but it works thanks.
it pretty much boils down to wrapping gui dependant modules with lib.mkIf