infinite recursion with nixos-hardware module
Hi!
I ran into an infinite recursion problem while trying to import a (soon-to-be) module from nixos-hardware, this one: https://github.com/NixOS/nixos-hardware/pull/1269
❯ nix flake check
warning: Git tree '/home/jkuball/Git/nix' is dirty
warning: unknown flake output '__functor'
evaluation warning: lib.nixos.evalModules is experimental and subject to change. See nixos/lib/default.nix
error:
… while checking flake output 'nixosConfigurations'
… while calling the 'elemAt' builtin
at /nix/store/jv5rs7mrlhkphzfkjpk6jlddi2g1nm46-source/grow/grow-on.nix:79:11:
78| if length values == 1 || head a then
79| elemAt a 1
| ^
80| else
… while calling the 'head' builtin
at /nix/store/jv5rs7mrlhkphzfkjpk6jlddi2g1nm46-source/grow/grow-on.nix:65:92:
64| v1 = !(isAttrs l && isAttrs r);
65| v2 = if attrPath == ["__std" "ci"] || attrPath == ["__std" "init"] then flatten v else head v;
| ^
66| in [v1 v2];
… while evaluating the module argument `config' in "/nix/store/isjriv0b9spxk3hca9zjpk3clbvvqjr9-source/module.nix":
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
error: infinite recursion encountered
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:245:34:
244| (regularModules ++ [ internalModule ])
245| ({ inherit lib options config specialArgs; } // specialArgs);
| ^
246| in mergeModules prefix (reverseList collected);
I am not sure whether this is helpful, but I have added the full trace below.
nix flake check --show-trace
❯ nix flake check --show-trace
warning: Git tree '/home/jkuball/Git/nix' is dirty
warning: unknown flake output '__functor'
evaluation warning: lib.nixos.evalModules is experimental and subject to change. See nixos/lib/default.nix
error:
… while checking flake output 'nixosConfigurations'
… while calling anonymous lambda
at /nix/store/jv5rs7mrlhkphzfkjpk6jlddi2g1nm46-source/grow/grow-on.nix:73:26:
72| let f = attrPath:
73| l.zipAttrsWith (n: values:
| ^
74| let
… while calling the 'elemAt' builtin
at /nix/store/jv5rs7mrlhkphzfkjpk6jlddi2g1nm46-source/grow/grow-on.nix:79:11:
78| if length values == 1 || head a then
79| elemAt a 1
| ^
80| else
… while calling the 'head' builtin
at /nix/store/jv5rs7mrlhkphzfkjpk6jlddi2g1nm46-source/grow/grow-on.nix:65:92:
64| v1 = !(isAttrs l && isAttrs r);
65| v2 = if attrPath == ["__std" "ci"] || attrPath == ["__std" "init"] then flatten v else head v;
| ^
66| in [v1 v2];
… from call site
at /nix/store/hdayw05q3ba4ax7gql5v49l2la409wmw-source/flake.nix:57:33:
56| {
57| nixosConfigurations = collectSystems self "nixosConfigurations";
| ^
58| darwinConfigurations = collectSystems self "darwinConfigurations";
… while calling '__functor'
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/collect.nix:34:27:
33| renamer = cell: target: "${cell}-${target}";
34| __functor = self: Self: CellBlock:
| ^
35| if builtins.hasAttr CellBlock collectors
… from call site
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/collect.nix:36:10:
35| if builtins.hasAttr CellBlock collectors
36| then collectors.${CellBlock} self.renamer Self
| ^
37| else
… while calling 'walk'
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/collectors/nixosConfigurations.nix:12:10:
11|
12| walk = self:
| ^
13| walkPaisano self cellBlock (system: cell: [
… from call site
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/collectors/nixosConfigurations.nix:13:5:
12| walk = self:
13| walkPaisano self cellBlock (system: cell: [
| ^
14| (l.mapAttrs (target: config: {
… while calling 'walkPaisano'
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/walkPaisano.nix:4:39:
3|
4| walkPaisano = self: cellBlock: ops: namer:
| ^
5| l.pipe (
… while calling the 'foldl'' builtin
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/walkPaisano.nix:5:5:
4| walkPaisano = self: cellBlock: ops: namer:
5| l.pipe (
| ^
6| l.mapAttrs (system:
… while calling anonymous lambda
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/trivial.nix:131:30:
130| */
131| pipe = builtins.foldl' (x: f: f x);
| ^
132|
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/trivial.nix:131:33:
130| */
131| pipe = builtins.foldl' (x: f: f x);
| ^
132|
… while calling 'collect'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:866:5:
865| pred:
866| attrs:
| ^
867| if pred attrs then
… while calling the 'concatMap' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:870:7:
869| else if isAttrs attrs then
870| concatMap (collect pred) (attrValues attrs)
| ^
871| else
… while calling 'collect'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:866:5:
865| pred:
866| attrs:
| ^
867| if pred attrs then
… while calling the 'concatMap' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:870:7:
869| else if isAttrs attrs then
870| concatMap (collect pred) (attrValues attrs)
| ^
871| else
… while calling 'collect'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:866:5:
865| pred:
866| attrs:
| ^
867| if pred attrs then
… while evaluating a branch condition
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:867:5:
866| attrs:
867| if pred attrs then
| ^
868| [ attrs ]
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:867:8:
866| attrs:
867| if pred attrs then
| ^
868| [ attrs ]
… while calling anonymous lambda
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/walkPaisano.nix:16:19:
15| ) [
16| (l.collect (x: x ? name && x ? value))
| ^
17| l.listToAttrs
… in the left operand of the AND (&&) operator
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/walkPaisano.nix:16:31:
15| ) [
16| (l.collect (x: x ? name && x ? value))
| ^
17| l.listToAttrs
… from call site
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/walkPaisano.nix:16:22:
15| ) [
16| (l.collect (x: x ? name && x ? value))
| ^
17| l.listToAttrs
… while calling anonymous lambda
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/walkPaisano.nix:7:27:
6| l.mapAttrs (system:
7| l.mapAttrs (cell: blocks: (
| ^
8| l.pipe blocks (
… while calling the 'foldl'' builtin
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/walkPaisano.nix:8:11:
7| l.mapAttrs (cell: blocks: (
8| l.pipe blocks (
| ^
9| [(l.attrByPath [cellBlock] {})]
… while calling anonymous lambda
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/trivial.nix:131:30:
130| */
131| pipe = builtins.foldl' (x: f: f x);
| ^
132|
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/trivial.nix:131:33:
130| */
131| pipe = builtins.foldl' (x: f: f x);
| ^
132|
… while calling 'filterAttrs'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:646:5:
645| pred:
646| set:
| ^
647| removeAttrs set (filter (name: ! pred name set.${name}) (attrNames set));
… while calling the 'removeAttrs' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:647:5:
646| set:
647| removeAttrs set (filter (name: ! pred name set.${name}) (attrNames set));
| ^
648|
… while calling the 'filter' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:647:22:
646| set:
647| removeAttrs set (filter (name: ! pred name set.${name}) (attrNames set));
| ^
648|
… while calling anonymous lambda
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:647:30:
646| set:
647| removeAttrs set (filter (name: ! pred name set.${name}) (attrNames set));
| ^
648|
… in the argument of the not operator
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:647:38:
646| set:
647| removeAttrs set (filter (name: ! pred name set.${name}) (attrNames set));
| ^
648|
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:647:38:
646| set:
647| removeAttrs set (filter (name: ! pred name set.${name}) (attrNames set));
| ^
648|
… while calling anonymous lambda
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/collectors/nixosConfigurations.nix:20:26:
19| (l.mapAttrs (_: transformers.nixosConfigurations))
20| (l.filterAttrs (_: config: config.bee.system == system))
| ^
21| (l.mapAttrs (_: config: config.bee._evaled))
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:647:48:
646| set:
647| removeAttrs set (filter (name: ! pred name set.${name}) (attrNames set));
| ^
648|
… from call site
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/transformers/nixosConfigurations.nix:4:4:
3| root,
4| }: {
| ^
5| evaled,
… while calling 'check'
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/checks/bee.nix:9:11:
8|
9| check = locatedConfig: let
| ^
10| checked = l.nixos.evalModules {
… in the condition of the assert statement
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/checks/bee.nix:28:5:
27| in
28| assert l.isAttrs asserted; {
| ^
29| inherit locatedConfig;
… while calling the 'isAttrs' builtin
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/checks/bee.nix:28:12:
27| in
28| assert l.isAttrs asserted; {
| ^
29| inherit locatedConfig;
… while evaluating a branch condition
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/checks/bee.nix:24:7:
23| asserted =
24| if failedAsserts != []
| ^
25| then throw "\nHive's layer sanitation boundary: \n${l.concatStringsSep "\n" (map (x: "- ${x}") failedAsserts)}"
… while calling the 'map' builtin
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/checks/bee.nix:21:21:
20|
21| failedAsserts = map (x: x.message) (l.filter (x: !x.assertion) checked.config.bee._alerts);
| ^
22|
… while calling the 'filter' builtin
at /nix/store/ziiqwyqp7ybawf6s7h9553qkw9gxnahy-source/src/checks/bee.nix:21:41:
20|
21| failedAsserts = map (x: x.message) (l.filter (x: !x.assertion) checked.config.bee._alerts);
| ^
22|
… while evaluating the attribute 'config.bee._alerts'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:334:9:
333| options = checked options;
334| config = checked (removeAttrs config [ "_module" ]);
| ^
335| _module = checked (config._module);
… while calling the 'seq' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:334:18:
333| options = checked options;
334| config = checked (removeAttrs config [ "_module" ]);
| ^
335| _module = checked (config._module);
… while evaluating a branch condition
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:273:9:
272| checkUnmatched =
273| if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then
| ^
274| let
… in the left operand of the AND (&&) operator
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:273:72:
272| checkUnmatched =
273| if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then
| ^
274| let
… in the left operand of the AND (&&) operator
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:273:33:
272| checkUnmatched =
273| if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then
| ^
274| let
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:270:16:
269| # paths, meaning recursiveUpdate will never override any value
270| else recursiveUpdate freeformConfig declaredConfig;
| ^
271|
… while calling 'recursiveUpdate'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:1626:5:
1625| lhs:
1626| rhs:
| ^
1627| recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:1627:5:
1626| rhs:
1627| recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
| ^
1628|
… while calling 'recursiveUpdateUntil'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:1568:5:
1567| lhs:
1568| rhs:
| ^
1569| let f = attrPath:
… while calling the 'zipAttrsWith' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:1578:8:
1577| );
1578| in f [] [rhs lhs];
| ^
1579|
… while evaluating a branch condition
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:263:16:
262| }) merged.unmatchedDefns;
263| in if defs == [] then {}
| ^
264| else declaredConfig._module.freeformType.merge prefix defs;
… while calling the 'map' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:259:22:
258| let
259| defs = map (def: {
| ^
260| file = def.file;
… while evaluating the attribute 'unmatchedDefns'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:695:7:
694| # Transforms unmatchedDefnsByName into a list of definitions
695| unmatchedDefns =
| ^
696| if configs == []
… while calling the 'concatLists' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:702:11:
701| else
702| concatLists (mapAttrsToList (name: defs:
| ^
703| map (def: def // {
… while calling anonymous lambda
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:1095:10:
1094| attrs:
1095| map (name: f name attrs.${name}) (attrNames attrs);
| ^
1096|
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:1095:16:
1094| attrs:
1095| map (name: f name attrs.${name}) (attrNames attrs);
| ^
1096|
… while calling anonymous lambda
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:702:46:
701| else
702| concatLists (mapAttrsToList (name: defs:
| ^
703| map (def: def // {
… while calling the 'map' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:703:13:
702| concatLists (mapAttrsToList (name: defs:
703| map (def: def // {
| ^
704| # Set this so we know when the definition first left unmatched territory
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/attrsets.nix:1095:23:
1094| attrs:
1095| map (name: f name attrs.${name}) (attrNames attrs);
| ^
1096|
… while calling anonymous lambda
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:688:22:
687| # Propagate all unmatched definitions from nested option sets
688| mapAttrs (n: v: v.unmatchedDefns) resultsByName
| ^
689| # Plus the definitions for the current prefix that don't have a matching option
… while evaluating the attribute 'unmatchedDefns'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:695:7:
694| # Transforms unmatchedDefnsByName into a list of definitions
695| unmatchedDefns =
| ^
696| if configs == []
… while evaluating a branch condition
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:696:9:
695| unmatchedDefns =
696| if configs == []
| ^
697| then
… while calling the 'concatLists' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:640:19:
639| loc = prefix ++ [name];
640| defns = pushedDownDefinitionsByName.${name} or [];
| ^
641| defns' = rawDefinitionsByName.${name} or [];
… while calling anonymous lambda
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:600:21:
599| mapAttrs
600| (n: value:
| ^
601| map (config: { inherit (module) file; inherit config; }) (pushDownProperties value)
… while calling the 'map' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:601:19:
600| (n: value:
601| map (config: { inherit (module) file; inherit config; }) (pushDownProperties value)
| ^
602| )
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:601:77:
600| (n: value:
601| map (config: { inherit (module) file; inherit config; }) (pushDownProperties value)
| ^
602| )
… while calling 'pushDownProperties'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:913:24:
912| */
913| pushDownProperties = cfg:
| ^
914| if cfg._type or "" == "merge" then
… while calling the 'map' builtin
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:917:7:
916| else if cfg._type or "" == "if" then
917| map (mapAttrs (n: v: mkIf cfg.condition v)) (pushDownProperties cfg.content)
| ^
918| else if cfg._type or "" == "override" then
… from call site
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:917:52:
916| else if cfg._type or "" == "if" then
917| map (mapAttrs (n: v: mkIf cfg.condition v)) (pushDownProperties cfg.content)
| ^
918| else if cfg._type or "" == "override" then
… while calling 'pushDownProperties'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:913:24:
912| */
913| pushDownProperties = cfg:
| ^
914| if cfg._type or "" == "merge" then
… while evaluating a branch condition
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:914:5:
913| pushDownProperties = cfg:
914| if cfg._type or "" == "merge" then
| ^
915| concatMap pushDownProperties cfg.contents
… while evaluating the attribute 'content'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:1038:25:
1037| { _type = "if";
1038| inherit condition content;
| ^
1039| };
… from call site
at /nix/store/isjriv0b9spxk3hca9zjpk3clbvvqjr9-source/module.nix:3:9:
2| let
3| cfg = config.disko;
| ^
4|
… while calling anonymous lambda
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:513:35:
512| context = name: ''while evaluating the module argument `${name}' in "${key}":'';
513| extraArgs = mapAttrs (name: _:
| ^
514| addErrorContext (context name)
… while evaluating the module argument `config' in "/nix/store/isjriv0b9spxk3hca9zjpk3clbvvqjr9-source/module.nix":
… while evaluating the attribute 'config'
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:245:34:
244| (regularModules ++ [ internalModule ])
245| ({ inherit lib options config specialArgs; } // specialArgs);
| ^
246| in mergeModules prefix (reverseList collected);
error: infinite recursion encountered
at /nix/store/zgzjib5vbxl9l2ridhjfvs1ll6lil8s6-source/lib/modules.nix:245:34:
244| (regularModules ++ [ internalModule ])
245| ({ inherit lib options config specialArgs; } // specialArgs);
| ^
246| in mergeModules prefix (reverseList collected);
I already tried to understand the problem, but I only found out the source of the error. The module extends the nixos boot.loader by a new option:
options = {
boot.loader.kboot-conf = {
# ...
If I change this to be something top level, like just kboot-conf, everything is fine. Is it illegal to extend original nixos module options, or is it just something that hive does not support?
Sadly I couldn't get a minimal example to also crash. But I presume it is reproducable by just adding github:KhashayarDanesh/nixos-hardware to the flake inputs and importing inputs.nixos-hardware.nixosModules.hardkernel-odroid-m1.
I'd love to get some help, or at least pointers on what to do. The easy way to fix it would probably be just to ask the PR maintainer to change the option name, but that feels wrong to me.
Thanks!
You can try put the nix code into a new file and import the file, see if that works?
Copying the module and then importing it from there sadly still results in the same error. The only consistent thing I found to do is to remove the boot.loader prefix from the option name :/
Testing a little bit around at least brought me on how to replicate it easily:
❯ cat apiary/colony/hardwareProfiles/nicky/default.nix
{
imports = [
./test
];
}
❯ cat apiary/colony/hardwareProfiles/nicky/test/default.nix
{ lib, ... }:
{
options = {
boot.loader."test".enable = lib.mkEnableOption "enable test";
};
config = { };
}
I am importing that hardwareProfile in a nixosConfiguration that is using an aarch64-linux bee. But it happens at import time and such is reproducable on a x86_64-linux doing a nix flake check.
@jkuball Hihi, I'm open to changing the option name if removing the boot.loader prefix doesn't violate the nixos naming conventions (if there are and someone knows where I could find them, Would be super happy to abide). From my side, there are no reasons to prefix the option with boot.loader except for the fact that I saw some other SBC bootloader config options were named in the same way.
I'm curious to know why this specific option name is causing problems though.
Also, I'm new to this and a large chunk of this module is copy-pasted things (sources are mentioned in the module files) I'm figuring out, so I'm super happy with suggestions and pointers as well.
Hey @KhashayarDanesh, thanks for reaching out! :)
I would say your hardware module is totally fine with extending the boot loader list. I mean, this is exactly what it is doing. My problems with hive seem to be unrelated to your PR.
In fact, I did try to build a minimal repro today so I could share it here, but: I can't get the problem to trigger on a simple setup. It has to be something else that I am doing in my configuration, so I will try to find the root cause and come back later, hopefully with more intel.
Hi! I am back!
I ignored this issue for weeks now, but recently I ran into the same problem again, after I updated my flake input facter-nixos-modules -- same infinite recursion error. So I tried to find the source of it, again with no luck.
But I could create a minimal reproducing hive configuration in a repository: https://github.com/jkuball/hive-reproduce-39
Just look at this block of code, and reproduce the error with a nix flake check.
The thing is, the same thing (importing disko & extending the options) does NOT result in an infinite recursion error in a flake not using hive or any other framework at all. So sadly this seems to be a hive issue (or at least a hive/disko incompatibility).
Hopefully that context & repro helps anyone, and even if it is me trying to fix this by myself in the future :)
This happens in a context of https://github.com/divnix/hive/blob/main/flake.nix#L98 where loader & src has evaluated, but i or any member might still be a thunk (which in my view narrows down the place to look for a potential issue).
@blaggacao I had this exact same issue in my config because I use lanzaboote together with disko. The infinite recursion is caused by setting a config freeform type (done by the bee checker): https://github.com/divnix/hive/blob/05ae75ec5a91761a9879d36bec0021c7668b1a6d/src/checks/bee.nix#L16
This causes a problem because disko sets the whole config.boot option to a mkIf and when an option under boot is defined an infinite recursion occurs when NixOS's evalModules tries to merge definitions.
I solved by using a custom checker which sets _module.check = false without setting freeeformtype to unspecified, but don't know if this is acceptable for the default nixos bee checker. (_module.freeformType = mkForce null also works but would need to be set in every config and will also break _module.check checks)
Very interesting analysis! Thank you!
Would this potentially work instead of the current simple ubspecified?
freeformType = with types; lazyAttrsOf (uniq unspecified);
I've seen that in nixpkgs anf it intuits like something something counter-recursion.
@blaggacao Sorry for the late reply, but I was busy and still wanted to debug a bit (a lot actually) and find out what was actually the cause.
Setting freeformType as you suggested didn't work, in fact the problem is not related to freeformType actual type, but to the fact that the config needs to be evaluated when evalModules tries to separate matched and unmatched options (in order to set the type for unmatched ones).
In this specific case:
- disko sets many options with a default value that depends on some other options (such as
config.boot.loader.) - the
virtualisation.vmVariantWithDiskodefines an interactive vm based on the nixpkgs/nixos' qemu-vm module (which requiresmodulesPathargument to be set) - some defaults for disko options require
pkgsargument.
Is there a reason for running the module check before evaluating the configuration (eval-config already performs the module check)? It seems to me that the bee check is only needed for evaluating bee options needed by the nixosConfigurations transformer (which uses the evaled attribute when calling eval-config).
Maybe a solution would be to simply evaluate the configuration without checking the modules (so that we the nixosconfigurations transformer has a way to use the specified bee configuration) and leave the module checking to be done by eval-config.
I don't have issues with nixos-hardware, I do have a similar issue with stylix. I was hoping to find possible solutions here and am willing to help you. what nixos-hardware modules are you using?
Hey DockterTeagle! I had the issue initially with this module on my odroid m1. But I also faced similar issues with stylix, too. I still don't have a solution, sadly. If you want to give it a go, I'd be delighted! But I also would advise you to read the previous discussion thoroughly, there are quite some learnings inside of it already. I also provided a reproducing repository: nix flake check github:jkuball/hive-reproduce-39.
where are you importing said module, do you import other nixos-hardware configs and it works fine but this one?
Hey DockerTeagle,
Yes, most if not all nixos-hardware modules work fine. A way to trigger the infinite recursion is to import disko and extend the "boot.loader" submodule option, like I did here: https://github.com/jkuball/hive-reproduce-39/blob/main/cells/hive/nixosConfigurations/repro.nix#L21
I just updated all flake inputs in that repository, the issue still persists.