NixOS / nixpkgs

Nix Packages collection & NixOS
MIT License
18.14k stars 14.17k forks source link

An infinite recursion in `nix.settings` #181427

Open 8573 opened 2 years ago

8573 commented 2 years ago

Describe the bug

When I run nixos-rebuild switch --upgrade, an infinite recursion error is thrown near a call to a function warnDeprecation. This seems possibly related to #175196, which is said to have been fixed in #175265.

Output of `nixos-rebuild --keep-going switch --upgrade --show-trace` ``` unpacking channels... building Nix... building the system configuration... error: infinite recursion encountered at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:292:72: 291| # For definitions that have an associated option 292| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options; | ^ 293| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20: 400| then recurse (path ++ [name]) value 401| else f (path ++ [name]) value; | ^ 402| in mapAttrs g; … while evaluating 'g' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19: 397| g = 398| name: value: | ^ 399| if isAttrs value && cond value … from call site … while evaluating the attribute 'content' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:898:14: 897| { _type = "if"; 898| inherit condition content; | ^ 899| }; … while evaluating 'dischargeProperties' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:827:25: 826| */ 827| dischargeProperties = def: | ^ 828| if def._type or "" == "merge" then … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:833:11: 832| if def.condition then 833| dischargeProperties def.content | ^ 834| else … while evaluating 'dischargeProperties' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:827:25: 826| */ 827| dischargeProperties = def: | ^ 828| if def._type or "" == "merge" then … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:756:137: 755| defs' = concatMap (m: 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) | ^ 757| ) defs; … while evaluating definitions from `/etc/nixos/sections/nix': … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:28: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:17: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:868:7: 867| in { 868| values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs; | ^ 869| inherit highestPrio; … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:769:9: 768| in { 769| values = defs'''; | ^ 770| inherit (defs'') highestPrio; … while evaluating the attribute 'optionalValue' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:787:5: 786| 787| optionalValue = | ^ 788| if isDefined then { value = mergedValue; } … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/types.nix:432:86: 431| merge = loc: defs: 432| mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs: | ^ 433| (mergeDefinitions (loc ++ [name]) elemType defs).optionalValue … from call site … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/types.nix:432:51: 431| merge = loc: defs: 432| mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs: | ^ 433| (mergeDefinitions (loc ++ [name]) elemType defs).optionalValue … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:225:62: 224| filterAttrs = pred: set: 225| listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set)); | ^ 226| … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:225:29: 224| filterAttrs = pred: set: 225| listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set)); | ^ 226| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:225:18: 224| filterAttrs = pred: set: 225| listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set)); | ^ 226| … while evaluating 'filterAttrs' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:224:23: 223| */ 224| filterAttrs = pred: set: | ^ 225| listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set)); … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/types.nix:432:35: 431| merge = loc: defs: 432| mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs: | ^ 433| (mergeDefinitions (loc ++ [name]) elemType defs).optionalValue … while evaluating 'merge' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/types.nix:431:20: 430| check = isAttrs; 431| merge = loc: defs: | ^ 432| mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs: … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:302:18: 301| in if defs == [] then {} 302| else declaredConfig._module.freeformType.merge prefix defs; | ^ 303| … while evaluating 'recursiveUpdateUntil' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:516:37: 515| */ 516| recursiveUpdateUntil = pred: lhs: rhs: | ^ 517| let f = attrPath: … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:308:16: 307| # paths, meaning recursiveUpdate will never override any value 308| else recursiveUpdate freeformConfig declaredConfig; | ^ 309| … while evaluating the attribute 'config' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:357:9: 356| options = checked options; 357| config = checked (removeAttrs config [ "_module" ]); | ^ 358| _module = checked (config._module); … while evaluating 'merge' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/types.nix:647:22: 646| check = x: isAttrs x || isFunction x || path.check x; 647| merge = loc: defs: | ^ 648| (base.extendModules { … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:777:59: 776| if isDefined then 777| if all (def: type.check def.value) defsFinal then type.merge loc defsFinal | ^ 778| else let allInvalid = filter (def: ! type.check def.value) defsFinal; … while evaluating the attribute 'mergedValue' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:775:5: 774| # Type-check the remaining definitions, and merge them. Or throw if no definitions. 775| mergedValue = | ^ 776| if isDefined then … while evaluating the option `nix.settings': … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:292:72: 291| # For definitions that have an associated option 292| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options; | ^ 293| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20: 400| then recurse (path ++ [name]) value 401| else f (path ++ [name]) value; | ^ 402| in mapAttrs g; … while evaluating 'g' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19: 397| g = 398| name: value: | ^ 399| if isAttrs value && cond value … from call site … while evaluating 'max' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/trivial.nix:246:12: 245| /* Return maximum of two numbers. */ 246| max = x: y: if x > y then x else y; | ^ 247| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/services/misc/nix-daemon.nix:787:35: 786| 787| nix.nrBuildUsers = mkDefault (max 32 (if cfg.settings.max-jobs == "auto" then 0 else cfg.settings.max-jobs)); | ^ 788| … while evaluating the attribute 'value.content' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:913:14: 912| { _type = "override"; 913| inherit priority content; | ^ 914| }; … while evaluating the attribute 'value._type' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:866:73: 865| highestPrio = foldl' (prio: def: min (getPrio def) prio) 9999 defs; 866| strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def; | ^ 867| in { … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:765:19: 764| # Avoid sorting if we don't have to. 765| if any (def: def.value._type or "" == "order") defs''.values | ^ 766| then sortProperties defs''.values … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:765:14: 764| # Avoid sorting if we don't have to. 765| if any (def: def.value._type or "" == "order") defs''.values | ^ 766| then sortProperties defs''.values … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:769:9: 768| in { 769| values = defs'''; | ^ 770| inherit (defs'') highestPrio; … while evaluating the attribute 'mergedValue' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:775:5: 774| # Type-check the remaining definitions, and merge them. Or throw if no definitions. 775| mergedValue = | ^ 776| if isDefined then … while evaluating the option `nix.nrBuildUsers': … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:292:72: 291| # For definitions that have an associated option 292| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options; | ^ 293| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20: 400| then recurse (path ++ [name]) value 401| else f (path ++ [name]) value; | ^ 402| in mapAttrs g; … while evaluating 'g' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19: 397| g = 398| name: value: | ^ 399| if isAttrs value && cond value … from call site … while evaluating 'range' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/lists.nix:300:5: 299| # Last integer in the range 300| last: | ^ 301| if first > last then … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/services/misc/nix-daemon.nix:30:52: 29| 30| nixbldUsers = listToAttrs (map makeNixBuildUser (range 1 cfg.nrBuildUsers)); | ^ 31| … while evaluating the attribute 'content' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:898:14: 897| { _type = "if"; 898| inherit condition content; | ^ 899| }; … while evaluating 'dischargeProperties' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:827:25: 826| */ 827| dischargeProperties = def: | ^ 828| if def._type or "" == "merge" then … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:833:11: 832| if def.condition then 833| dischargeProperties def.content | ^ 834| else … while evaluating 'dischargeProperties' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:827:25: 826| */ 827| dischargeProperties = def: | ^ 828| if def._type or "" == "merge" then … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:756:137: 755| defs' = concatMap (m: 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) | ^ 757| ) defs; … while evaluating definitions from `/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/services/misc/nix-daemon.nix': … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:28: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:17: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:868:7: 867| in { 868| values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs; | ^ 869| inherit highestPrio; … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:769:9: 768| in { 769| values = defs'''; | ^ 770| inherit (defs'') highestPrio; … while evaluating the attribute 'mergedValue' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:775:5: 774| # Type-check the remaining definitions, and merge them. Or throw if no definitions. 775| mergedValue = | ^ 776| if isDefined then … while evaluating the option `users.users': … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:292:72: 291| # For definitions that have an associated option 292| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options; | ^ 293| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20: 400| then recurse (path ++ [name]) value 401| else f (path ++ [name]) value; | ^ 402| in mapAttrs g; … while evaluating 'g' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19: 397| g = 398| name: value: | ^ 399| if isAttrs value && cond value … from call site … while evaluating 'filterAttrs' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:224:23: 223| */ 224| filterAttrs = pred: set: | ^ 225| listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set)); … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/config/users-groups.nix:616:9: 615| }; 616| }) (filterAttrs (_: u: u.packages != []) cfg.users)); | ^ 617| … while evaluating 'mapAttrs'' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:339:18: 338| */ 339| mapAttrs' = f: set: | ^ 340| listToAttrs (map (attr: f attr set.${attr}) (attrNames set)); … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/config/users-groups.nix:608:24: 607| 608| environment.etc = (mapAttrs' (_: { packages, name, ... }: { | ^ 609| name = "profiles/per-user/${name}"; … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:576:44: 575| defnsByName' = byName "config" (module: value: 576| [{ inherit (module) file; inherit value; }] | ^ 577| ) configs; … while evaluating 'dischargeProperties' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:827:25: 826| */ 827| dischargeProperties = def: | ^ 828| if def._type or "" == "merge" then … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:756:137: 755| defs' = concatMap (m: 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) | ^ 757| ) defs; … while evaluating definitions from `/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/config/users-groups.nix': … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:28: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:17: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:868:7: 867| in { 868| values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs; | ^ 869| inherit highestPrio; … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:769:9: 768| in { 769| values = defs'''; | ^ 770| inherit (defs'') highestPrio; … while evaluating the attribute 'mergedValue' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:775:5: 774| # Type-check the remaining definitions, and merge them. Or throw if no definitions. 775| mergedValue = | ^ 776| if isDefined then … while evaluating the option `environment.etc': … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:292:72: 291| # For definitions that have an associated option 292| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options; | ^ 293| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20: 400| then recurse (path ++ [name]) value 401| else f (path ++ [name]) value; | ^ 402| in mapAttrs g; … while evaluating 'g' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19: 397| g = 398| name: value: | ^ 399| if isAttrs value && cond value … from call site … while evaluating the attribute 'default' at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/config/resolvconf.nix:50:9: 49| type = types.bool; 50| default = !(config.environment.etc ? "resolv.conf"); | ^ 51| defaultText = literalExpression ''!(config.environment.etc ? "resolv.conf")''; … while evaluating the attribute 'value.content' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:913:14: 912| { _type = "override"; 913| inherit priority content; | ^ 914| }; … while evaluating the attribute 'value._type' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:866:73: 865| highestPrio = foldl' (prio: def: min (getPrio def) prio) 9999 defs; 866| strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def; | ^ 867| in { … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:765:19: 764| # Avoid sorting if we don't have to. 765| if any (def: def.value._type or "" == "order") defs''.values | ^ 766| then sortProperties defs''.values … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:765:14: 764| # Avoid sorting if we don't have to. 765| if any (def: def.value._type or "" == "order") defs''.values | ^ 766| then sortProperties defs''.values … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:769:9: 768| in { 769| values = defs'''; | ^ 770| inherit (defs'') highestPrio; … while evaluating the attribute 'mergedValue' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:775:5: 774| # Type-check the remaining definitions, and merge them. Or throw if no definitions. 775| mergedValue = | ^ 776| if isDefined then … while evaluating the option `networking.resolvconf.enable': … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:292:72: 291| # For definitions that have an associated option 292| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options; | ^ 293| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20: 400| then recurse (path ++ [name]) value 401| else f (path ++ [name]) value; | ^ 402| in mapAttrs g; … while evaluating 'g' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19: 397| g = 398| name: value: | ^ 399| if isAttrs value && cond value … from call site … while evaluating the attribute 'condition' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:898:14: 897| { _type = "if"; 898| inherit condition content; | ^ 899| }; … while evaluating the attribute 'condition' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:898:14: 897| { _type = "if"; 898| inherit condition content; | ^ 899| }; … while evaluating the attribute 'condition' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:898:14: 897| { _type = "if"; 898| inherit condition content; | ^ 899| }; … while evaluating 'dischargeProperties' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:827:25: 826| */ 827| dischargeProperties = def: | ^ 828| if def._type or "" == "merge" then … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:756:137: 755| defs' = concatMap (m: 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) | ^ 757| ) defs; … while evaluating definitions from `/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/config/resolvconf.nix': … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:28: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:17: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:868:7: 867| in { 868| values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs; | ^ 869| inherit highestPrio; … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:769:9: 768| in { 769| values = defs'''; | ^ 770| inherit (defs'') highestPrio; … while evaluating the attribute 'mergedValue' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:775:5: 774| # Type-check the remaining definitions, and merge them. Or throw if no definitions. 775| mergedValue = | ^ 776| if isDefined then … while evaluating the option `systemd.services': … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:292:72: 291| # For definitions that have an associated option 292| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options; | ^ 293| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20: 400| then recurse (path ++ [name]) value 401| else f (path ++ [name]) value; | ^ 402| in mapAttrs g; … while evaluating 'g' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19: 397| g = 398| name: value: | ^ 399| if isAttrs value && cond value … from call site … while evaluating 'mapAttrsToList' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:355:23: 354| */ 355| mapAttrsToList = f: attrs: | ^ 356| map (name: f name attrs.${name}) (attrNames attrs); … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/security/systemd-confinement.nix:146:40: 145| 146| config.assertions = lib.concatLists (lib.mapAttrsToList (name: cfg: let | ^ 147| whatOpt = optName: "The 'serviceConfig' option '${optName}' for" … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:576:44: 575| defnsByName' = byName "config" (module: value: 576| [{ inherit (module) file; inherit value; }] | ^ 577| ) configs; … while evaluating 'dischargeProperties' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:827:25: 826| */ 827| dischargeProperties = def: | ^ 828| if def._type or "" == "merge" then … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:756:137: 755| defs' = concatMap (m: 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) | ^ 757| ) defs; … while evaluating definitions from `/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/security/systemd-confinement.nix': … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:28: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:17: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:868:7: 867| in { 868| values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs; | ^ 869| inherit highestPrio; … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:769:9: 768| in { 769| values = defs'''; | ^ 770| inherit (defs'') highestPrio; … while evaluating the attribute 'mergedValue' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:775:5: 774| # Type-check the remaining definitions, and merge them. Or throw if no definitions. 775| mergedValue = | ^ 776| if isDefined then … while evaluating the option `assertions': … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:292:72: 291| # For definitions that have an associated option 292| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options; | ^ 293| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20: 400| then recurse (path ++ [name]) value 401| else f (path ++ [name]) value; | ^ 402| in mapAttrs g; … while evaluating 'g' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19: 397| g = 398| name: value: | ^ 399| if isAttrs value && cond value … from call site … while evaluating 'fold'' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/lists.nix:56:15: 55| len = length list; 56| fold' = n: | ^ 57| if n == len … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/lists.nix:60:8: 59| else op (elemAt list n) (fold' (n + 1)); 60| in fold' 0; | ^ 61| … while evaluating 'foldr' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/lists.nix:53:20: 52| */ 53| foldr = op: nul: list: | ^ 54| let … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/activation/top-level.nix:139:12: 138| # Replace runtime dependencies 139| system = foldr ({ oldDependency, newDependency }: drv: | ^ 140| pkgs.replaceDependency { inherit oldDependency newDependency drv; } … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:576:44: 575| defnsByName' = byName "config" (module: value: 576| [{ inherit (module) file; inherit value; }] | ^ 577| ) configs; … while evaluating 'dischargeProperties' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:827:25: 826| */ 827| dischargeProperties = def: | ^ 828| if def._type or "" == "merge" then … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:756:137: 755| defs' = concatMap (m: 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) | ^ 757| ) defs; … while evaluating definitions from `/nix/var/nix/profiles/per-user/root/channels/nixos/nixos/modules/system/activation/top-level.nix': … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:28: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:755:17: 754| # Process mkMerge and mkIf properties. 755| defs' = concatMap (m: | ^ 756| map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)) … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:868:7: 867| in { 868| values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs; | ^ 869| inherit highestPrio; … while evaluating the attribute 'values' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:769:9: 768| in { 769| values = defs'''; | ^ 770| inherit (defs'') highestPrio; … while evaluating the attribute 'mergedValue' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:775:5: 774| # Type-check the remaining definitions, and merge them. Or throw if no definitions. 775| mergedValue = | ^ 776| if isDefined then … while evaluating the option `system.build.toplevel': … while evaluating the attribute 'value' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:741:9: 740| in warnDeprecation opt // 741| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value; | ^ 742| inherit (res.defsFinal') highestPrio; … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/modules.nix:292:72: 291| # For definitions that have an associated option 292| declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options; | ^ 293| … from call site at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:401:20: 400| then recurse (path ++ [name]) value 401| else f (path ++ [name]) value; | ^ 402| in mapAttrs g; … while evaluating 'g' at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:398:19: 397| g = 398| name: value: | ^ 399| if isAttrs value && cond value … from call site … while evaluating anonymous lambda at /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:518:24: 517| let f = attrPath: 518| zipAttrsWith (n: values: | ^ 519| let here = attrPath ++ [n]; in … from call site time: nixos-rebuild --keep-going switch --upgrade --show-trace 5.72s user 29.63s system 98% cpu 35.882 total ```

In my NixOS configuration, I have the following:

{

  nix = {
    settings = {
      # ...
      max-jobs =
        lib.mkIf
        config.c74d-params.manages-own-store
        config.c74d-params.hardware.cores.virtual;
      min-free = lib.mkIf
        config.c74d-params.manages-own-store
        (let
          j = config.nix.settings.max-jobs;
          m = config.c74d-params.hardware.memory.main.gigabytes;
        in j * j * m * m * 1024 * 1024);
      # ...
    };
    # ...
  };

}

The infinite recursion does not occur if I comment out the setting of nix.settings.min-free. The configuration variables c74d-params.manages-own-store, c74d-params.hardware.cores.virtual, and c74d-params.hardware.memory.main.gigabytes are set simply to constants.

Notify maintainers

@roberth I suppose

Metadata

roberth commented 2 years ago

The problem here is that nix.settings has a freeformType based on attrsOf, which supports mkIf. Because of mkIf support, it behaves like

let
  settings = filterAttrs
    (k: v: isNotMkIfFalse v)
    (yourSettings settings);

  yourSettings = settings: {
    min-free = f settings.max-jobs;
  };

in settings

Crucially, filterAttrs can only return an attrset after evaluating all the actual values v.

Presumably one way to fix this is to change the freeformType to use lazyAttrsOf. Another way is to add all the known nix settings with their defaults as proper module system options. This way, we're not relying on the freeformType. This seems to work, as I can set nix.settings.max-jobs = config.nix.settings.cores; without infinite recursion.

Removing mkIf support from nix.settings seems like too much of a breaking change. Instead, adding more options to nix.settings does not break anything and improves the ux.

cc @infinisil did we document this behavior and a solution?

phiadaarr commented 2 years ago

I run into the same problem and I do not have enough knowledge to work on it. Could anyone give me some advice how to approach the problem and fix it?

Any help is very much appreciated!

roberth commented 2 years ago

@phiadaarr Did you confirm with --show-trace that nix.settings is involved in your infinite recursion? Does your nix.settings reference itself in any way?

If so, you could fix the problem by adding the option declarations you need to nix.settings.

infinisil commented 1 year ago

cc @infinisil did we document this behavior and a solution?

Yeah there's a note in a manual section recommending to declare options

roberth commented 1 year ago

It's easy to miss, so I've opened

roberth commented 1 year ago

max-jobs is a proper option. According to the manual, min-free would also have to be added, so this issue doesn't seem to have been resolved yet.