I can't find where “value is a function while a set was expected” comes from in my nix module

Hello, I’m trying to develop my first nix module with the aim of simplifying a VFIO installation and I’ve come across a simple type error. But after three days of going through my code, I can’t figure out where it’s coming from. So I think I’m missing something due to a lack of expertise.

Here’s the code:

{
  config,
  lib,
  pkgs,
  qemu_kvm,
  OVMF,
  virglrenderer,
  ...
}:
let
  cfg = config.virtualisation.virtualMachines;

  inherit (lib) mkIf mkOption types;
in {
  options = {
    virtualisation.virtualMachines = {
      enable = mkOption {
        type = types.bool;
        default = false;
      };
      username = mkOption { type = types.str; };

      sambaAccess = {
        enable = mkOption {
          type = types.bool;
          default = false;
        };
      };

      vmFolderPath = mkOption {
        type = types.str;
        default = "/home/${cfg.username}/VM";
      };
      isoFolderPath = mkOption {
        type = types.str;
        default = "${cfg.vmFolderPath}/ISO";
      };

      machines = mkOption {
        default = [];
        type = with types; listOf(submodule { options = {
          name = mkOption {
            type = types.str;
            default = "win11";
          };
          os = mkOption {
            type = types.str;
            default = "win11";
          };

          isoName = mkOption {
            type = types.str;
            default = "win11.iso";
          };

          hardware = {
            cores = mkOption {
              type = types.int;
              default = 2;
            };
            threads = mkOption {
              type = types.int;
              default = 2;
            };
            memory = mkOption {
              type = types.int;
              default = 8;
            };

            disk = {
              size = mkOption {
                type = types.int;
                default = 128;
              };
              path = mkOption {
                type = types.str;
                default = "${cfg.vmFolderPath}/DISK";
              };
              ssdEmulation = mkOption {
                type = types.bool;
                default = true;
              };
            };
          };

          passthrough = {
            enable = mkOption {
              type = types.bool;
              default = false;
            };

            restartDm = mkOption {
              type = types.bool;
              default = false;
            };

            pcies = mkOption {
              default = [];
              type = listOf(submodule { options = {
                lines = {
                  vmBus = mkOption {
                    type = types.str;
                    default = "09";
                  };
                  bus = mkOption {
                    type = types.str;
                    default = "";
                  };
                  slot = mkOption {
                    type = types.str;
                    default = "";
                  };
                  functions = mkOption {
                    type = listOf(types.str);
                    default = [];
                  };
                  ids = mkOption {
                    type = listOf(types.str);
                    default = [];
                  };
                };
                

                driver = mkOption {
                  type = types.str;
                  default = "";
                };

                blacklist = {
                  driver = mkOption {
                    type = types.bool;
                    default = false;
                  };
                  pcie = mkOption {
                    type = types.bool;
                    default = false;
                  };
                };
              };});
            };
          };
        };});
      };
    };
  };

  config = mkIf (cfg.enable) {
    boot = {
      initrd.kernelModules = [
        "vfio_pci"
        "vfio"
        "vfio_iommu_type1"
        "amdgpu"
      ];

      extraModprobeConfig = let
        baseConfig = ''
          options kvm_intel kvm_amd modeset=1
        '';


        vfioPciOptions = lib.concatStrings (
          builtins.map (vm:
            lib.optionalString vm.passthrough.enable
              (lib.concatStrings (lib.forEach vm.passthrough.pcies (pcie:
                lib.concatStrings (lib.forEach pcie.line.ids (id:
                  ''
                    options vfio-pci ids=${id}
                  ''
                )))))) cfg.machines);

        pciBlacklistOptions = lib.concatStrings (
          builtins.map (vm:
            lib.optionalString vm.passthrough.enable
              (lib.concatStrings (lib.forEach vm.passthrough.pcies (pcie:
                lib.optionalString (pcie.blacklist.driver)
                  ''
                    options ${pcie.driver} modeset=0
                    blacklist ${pcie.driver}
                  '')))) cfg.machines);

      in lib.concatStrings ([
        baseConfig
        vfioPciOptions
        pciBlacklistOptions
      ]);

      kernelParams = [
        "intel_iommu=on"
        "amd_iommu=on"
        "iommu=pt"
        "video=efifb:off"
      ];
    };

    services = {
      samba = lib.mkIf cfg.sambaAccess.enable {
        openFirewall = true;
        enable = true;
        securityType = "user";

        shares = {
          home = {
            path = "/home/${cfg.username}";
            browseable = "yes";
            writeable = "yes";
            "acl allow execute always" = true;
            "read only" = "no";
            "valid users" = "${cfg.username}";
            "create mask" = "0644";
            "directory mask" = "0755";
            "force user" = "${cfg.username}";
            "force group" = "users";
          };

          media = {
            path = "/run/media/${cfg.username}";
            browseable = "yes";
            writeable = "yes";
            "acl allow execute always" = true;
            "read only" = "no";
            "valid users" = "${cfg.username}";
            "create mask" = "0644";
            "directory mask" = "0755";
            "force user" = "${cfg.username}";
            "force group" = "users";
          };
        };
      };
    };

    virtualisation = lib.mkIf cfg.enable {
      libvirtd = {
        enable = true;
        qemu = {
          package = qemu_kvm;
          runAsRoot = true;
          swtpm.enable = true;
          ovmf = {
            enable = true;
            packages = [
              (OVMF.override {
                secureBoot = true;
                tpmSupport = true;
              }).fd
              virglrenderer
            ];
          };
        };
      };
    };

    systemd.services.libvirtd.preStart =
      lib.concatStrings (lib.forEach cfg.machines
    (vm:
      let
        ifElse = { condition, resultIf, resultElse }: (
          if condition
          then resultIf
          else resultElse
        );

        bindingPcie = let
          lines = { lines, function }: ''
            BUS="${lines.bus}"
            SLOT="${lines.slot}"
            FUNCTION="${function}"
            PCIE_FULL="$BUS:$SLOT.$FUNCTION"
            PCIE_ESCAPED="$BUS\\:$SLOT.$FUNCTION"
          '';

          unbindPciesSetter = pcie: lib.concatStrings (
            lib.forEach pcie.lines.functions (function: ''
              ${lines pcie.lines function}
              echo 0000:$PCIE_FULL \
                > /sys/bus/pci/devices/0000\:$PCIE_ESCAPED/driver/unbind \
                2> /dev/null
            '')
          );

          bindPciesSetter = pcie: lib.concatStrings (
            lib.forEach pcie.lines.functions (function: ''
              ${lines pcie.lines function}
              echo 0000:$PCIE_FULL > \
                /sys/bus/pci/drivers/${pcie.driver}/bind \
                2> /dev/null
            '')
          );

          blacklistCondition = blacklist: lib.optionalString (
            ! blacklist.driver
            && blacklist.pcie
          );

          bindingCondition = blacklist: lib.optionalString (
            ! blacklist.driver
            && ! blacklist.pcie
          );

          finalString = { condition, binding }: lib.optionalString vm.passthrough.enable (
            lib.concatStrings (builtins.map (pcie:
              (condition pcie.blacklist) (binding pcie)
            ) vm.passthrough.pcies)
          );

        in {
          bind = (finalString bindingCondition bindPciesSetter);
          unbind = (finalString bindingCondition unbindPciesSetter);
          blacklist = (finalString blacklistCondition unbindPciesSetter);
        };

        restartDmFormated = (lib.optionalString (
          vm.passthrough.enable
          && vm.passthrough.restartDm
        )
          "systemctl restart display-manager.service");

        pciesXml = (lib.optionalString (
          vm.passthrough.enable
        ) (
          lib.concatStrings (builtins.map (pcie: lib.concatStrings (
            lib.forEach pcie.lines.functions (function: ''
              <hostdev
                mode='subsystem'
                type='pci'
                managed='yes'
              >
                <source>
                  <address
                    domain='0x0000'
                    bus='0x${pcie.lines.bus}'
                    slot='0x${pcie.lines.slot}'
                    function='0x${function}'
                  />
                </source>
                <address
                  type='pci'
                  domain='0x0000'
                  bus='0x${pcie.lines.vmBus}'
                  slot='0x${pcie.lines.slot}'
                  function='0x${function}'
                />
                <!-- multifunction='on' -->
              </hostdev>
            '')
          )) vm.passthrough.pcies)
        ));

        videoVirtio = (ifElse (vm.passthrough.enable)
          ''
            <model type='none'/>
          ''
          ''
            <model type="virtio" heads="1" primary="yes">
              <acceleration accel3d="no"/>
            </model>
            <address
              type="pci"
              domain="0x0000"
              bus="0x00"
              slot="0x01"
              function="0x0"
            />
          '');

        graphicsVirtio = (ifElse (vm.passthrough.enable)
          ''
            <graphics type="spice" port="-1" autoport="no">
              <listen type="address"/>
              <image compression="off"/>
              <gl enable="no"/>
            </graphics>
          ''
          ''
            <graphics type='spice'>
              <listen type="none"/>
              <image compression="off"/>
              <gl enable="no"/>
            </graphics>
          '');

        ssdEmulation = (lib.optionalString vm.hardware.disk.ssdEmulation
          ''
            <qemu:override>
              <qemu:device alias="scsi0-0-0-0">
                <qemu:frontend>
                  <qemu:property name="rotation_rate" type="unsigned" value="1"/>
                </qemu:frontend>
              </qemu:device>
            </qemu:override>
          '');

        virtioIso = (lib.optionalString (vm.os == "win11") ''
          <disk type='file' device='cdrom'>
            <driver name='qemu' type='raw'/>
            <source file='${cfg.isoFolderPath}/virtio-win.iso'/>
            <target dev='sdc' bus='sata'/>
            <readonly/>
            <address type='drive' controller='0' bus='0' target='0' unit='2'/>
          </disk>
        '');

        osUrl = (ifElse (vm.os == "linux")
          "http://libosinfo.org/linux/2022"
          "http://microsoft.com/win/11");

        qemuHook = (pkgs.writeScript "qemu-hook" (
          builtins.replaceStrings [
            "{{ unbindPcies }}"
            "{{ bindPcies }}"
            "{{ restartDm }}"
            "{{ username }}"
          ] [
            (bindingPcie.unbind)
            (bindingPcie.bind)
            restartDmFormated
            (cfg.username)
          ] (builtins.readFile ./src/qemuHook.sh)
        ));

        templateConfig = (pkgs.writeText "template-config" (
          builtins.replaceStrings [
            "{{ vm.memory }}"
            "{{ vm.vcore }}"
            "{{ vm.cores }}"
            "{{ vm.threads }}"
            "{{ vm.pcies }}"
            "{{ vm.diskPath }}"
            "{{ videoVirtio }}"
            "{{ graphicsVirtio }}"
            "{{ vm.name }}"
            "{{ ssdEmulation }}"
            "{{ osUrl }}"
          ] [
            (toString vm.hardware.memory)
            (toString (vm.hardware.cores * vm.hardware.threads))
            (toString vm.hardware.cores)
            (toString vm.hardware.threads)
            pciesXml
            (vm.hardware.disk.path)
            videoVirtio
            graphicsVirtio
            (vm.name)
            ssdEmulation
            osUrl
          ] (builtins.readFile ./src/template.xml)
        ));

        templateSetupConfig = (pkgs.writeText "template-setup-config" (
          builtins.replaceStrings [
            "{{ vm.memory }}"
            "{{ vm.vcore }}"
            "{{ vm.cores }}"
            "{{ vm.threads }}"
            "{{ isoFolderPath }}"
            "{{ vm.diskPath }}"
            "{{ vm.name }}"
            "{{ ssdEmulation }}"
            "{{ virtioIso }}"
            "{{ osUrl }}"
            "{{ vm.isoName }}"
          ] [
            (toString vm.hardware.memory)
            (toString (vm.hardware.cores * vm.hardware.threads))
            (toString vm.hardware.cores)
            (toString vm.hardware.threads)
            (cfg.isoFolderPath)
            (vm.hardware.disk.path)
            (vm.name)
            ssdEmulation
            virtioIso
            osUrl
            (vm.isoName)
          ] (builtins.readFile ./src/template-setup.xml)
        ));

        pathISO = (pkgs.writeText "path-iso" (
          builtins.replaceStrings [
            "{{ isoFolderPath }}"
          ] [
            cfg.isoFolderPath
          ] (builtins.readFile ./src/ISO.xml)
        ));
      in
        ''
          ${bindingPcie.blacklist}

          mkdir -p /var/lib/libvirt/{hooks,qemu,storage}
          chmod 755 /var/lib/libvirt/{hooks,qemu,storage}

          if [ ! -f ${vm.hardware.disk.path}/${vm.name}.qcow2 ]; then
	          mkdir -p ${vm.hardware.disk.path}
            qemu-img create \
              -f qcow2 ${vm.hardware.disk.path}/${vm.name}.qcow2 \
              ${(toString vm.hardware.disk.size)}G
          fi

          # Copy hook files
          ln -sf ${qemuHook} /var/lib/libvirt/hooks/qemu.d/${vm.name}
          ln -sf ${pathISO} /var/lib/libvirt/storage/ISO.xml
          ln -sf ${templateConfig} /var/lib/libvirt/qemu/${vm.name}.xml
          ln -sf ${templateSetupConfig} /var/lib/libvirt/qemu/${vm.name}-setup.xml
        ''
    ));
  };
}

and here’s the error:

building the system configuration...
error:
       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1571:24:

         1570|     let f = attrPath:
         1571|       zipAttrsWith (n: values:
             |                        ^
         1572|         let here = attrPath ++ [n]; in

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1205:18:

         1204|         mapAttrs
         1205|           (name: value:
             |                  ^
         1206|             if isAttrs value && cond value

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1208:18:

         1207|             then recurse (path ++ [ name ]) value
         1208|             else f (path ++ [ name ]) value);
             |                  ^
         1209|     in

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

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

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:824:28:

          823|         # Process mkMerge and mkIf properties.
          824|         defs' = concatMap (m:
             |                            ^
          825|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)
)

       … while evaluating definitions from `/nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/nixos/modules/system/activation/top-level.nix':

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:825:137:

          824|         defs' = concatMap (m:
          825|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)
)
             |                                                                                                                                         ^
          826|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:896:25:

          895|   */
          896|   dischargeProperties = def:
             |                         ^
          897|     if def._type or "" == "merge" then

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/nixos/modules/system/activation/top-level.nix:71:12:

           70|   # Replace runtime dependencies
           71|   system = foldr ({ oldDependency, newDependency }: drv:
             |            ^
           72|       pkgs.replaceDependency { inherit oldDependency newDependency drv; }

       … while calling 'foldr'

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/lists.nix:121:20:

          120|   */
          121|   foldr = op: nul: list:
             |                    ^
          122|     let

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/lists.nix:128:8:

          127|         else op (elemAt list n) (fold' (n + 1));
          128|     in fold' 0;
             |        ^
          129|

       … while calling 'fold''

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/lists.nix:124:15:

          123|       len = length list;
          124|       fold' = n:
             |               ^
          125|         if n == len

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/nixos/modules/system/activation/top-level.nix:68:10:

           67|     then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
           68|     else showWarnings config.warnings baseSystem;
             |          ^
           69|

       … while calling 'showWarnings'

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/trivial.nix:867:28:

          866|
          867|   showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings;
             |                            ^
          868|

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/trivial.nix:867:33:

          866|
          867|   showWarnings = warnings: res: lib.foldr (w: x: warn w x) res warnings;
             |                                 ^
          868|

       … while calling 'foldr'

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/lists.nix:121:20:

          120|   */
          121|   foldr = op: nul: list:
             |                    ^
          122|     let

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/lists.nix:128:8:

          127|         else op (elemAt list n) (fold' (n + 1));
          128|     in fold' 0;
             |        ^
          129|

       … while calling 'fold''

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/lists.nix:124:15:

          123|       len = length list;
          124|       fold' = n:
             |               ^
          125|         if n == len

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1205:18:

         1204|         mapAttrs
         1205|           (name: value:
             |                  ^
         1206|             if isAttrs value && cond value

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1208:18:

         1207|             then recurse (path ++ [ name ]) value
         1208|             else f (path ++ [ name ]) value);
             |                  ^
         1209|     in

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

       … while evaluating the option `warnings':

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:824:28:

          823|         # Process mkMerge and mkIf properties.
          824|         defs' = concatMap (m:
             |                            ^
          825|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)
)

       … while evaluating definitions from `/nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/nixos/modules/system/boot/systemd.nix':

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:825:137:

          824|         defs' = concatMap (m:
          825|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)
)
             |                                                                                                                                         ^
          826|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:896:25:

          895|   */
          896|   dischargeProperties = def:
             |                         ^
          897|     if def._type or "" == "merge" then

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1096:10:

         1095|     attrs:
         1096|     map (name: f name attrs.${name}) (attrNames attrs);
             |          ^
         1097|

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1096:16:

         1095|     attrs:
         1096|     map (name: f name attrs.${name}) (attrNames attrs);
             |                ^
         1097|

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/nixos/modules/system/boot/systemd.nix:443:16:

          442|       mapAttrsToList
          443|         (name: service:
             |                ^
          444|           let

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/nixos/modules/system/boot/systemd.nix:450:16:

          449|             concatLists [
          450|               (optional (type == "oneshot" && (restart == "always" || restart == "on-success"))
             |                ^
          451|                 "Service '${name}.service' with 'Type=oneshot' cannot have 'Restart=always' or 'Restart=on-success'"

       … while calling 'optional'

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/lists.nix:784:20:

          783|   */
          784|   optional = cond: elem: if cond then [elem] else [];
             |                    ^
          785|

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1205:18:

         1204|         mapAttrs
         1205|           (name: value:
             |                  ^
         1206|             if isAttrs value && cond value

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1208:18:

         1207|             then recurse (path ++ [ name ]) value
         1208|             else f (path ++ [ name ]) value);
             |                  ^
         1209|     in

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

       … while evaluating the option `systemd.services.libvirtd.serviceConfig':

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:824:28:

          823|         # Process mkMerge and mkIf properties.
          824|         defs' = concatMap (m:
             |                            ^
          825|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)
)

       … while evaluating definitions from `/nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/nixos/modules/system/boot/systemd.nix':

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:825:137:

          824|         defs' = concatMap (m:
          825|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)
)
             |                                                                                                                                         ^
          826|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:896:25:

          895|   */
          896|   dischargeProperties = def:
             |                         ^
          897|     if def._type or "" == "merge" then

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1205:18:

         1204|         mapAttrs
         1205|           (name: value:
             |                  ^
         1206|             if isAttrs value && cond value

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/attrsets.nix:1208:18:

         1207|             then recurse (path ++ [ name ]) value
         1208|             else f (path ++ [ name ]) value);
             |                  ^
         1209|     in

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:242:72:

          241|           # For definitions that have an associated option
          242|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          243|

       … while evaluating the option `systemd.services.libvirtd.preStart':

       … while calling anonymous lambda

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:824:28:

          823|         # Process mkMerge and mkIf properties.
          824|         defs' = concatMap (m:
             |                            ^
          825|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)
)

       … while evaluating definitions from `/nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/flake.nix':

       … from call site

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:825:137:

          824|         defs' = concatMap (m:
          825|           map (value: { inherit (m) file; inherit value; }) (builtins.addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value)
)
             |                                                                                                                                         ^
          826|         ) defs;

       … while calling 'dischargeProperties'

         at /nix/store/0vpk9v6rj551q42ym4h9qrdx9xxxhcsg-source/lib/modules.nix:896:25:

          895|   */
          896|   dischargeProperties = def:
             |                         ^
          897|     if def._type or "" == "merge" then

       … while calling anonymous lambda

         at /nix/store/9lfys6q0szlcrz0rivkrjrh9wb8dc0nl-source/modules/virtualMachines/default.nix:255:6:

          254|       lib.concatStrings (lib.forEach cfg.machines
          255|     (vm:
             |      ^
          256|       let

       error: value is a function while a set was expected

thank you in advance to those who will take the time to read my problem

1 Like

Did you try to bisect your code by commenting one half out and try if the error still occurs? I think this is a more fruitful way to find the error instead of trying to understand the stacktrace. Because nix is a lazy untyped language it can throw such errors a lot of layers deep.

Looks like you have a few issues!

First, the stack trace isn’t useless; it tells you (scroll to the bottom, then look a few frames up) that it is failing while evaluating the option systemd.services.libvirtd.preStart. So that’s where to look first.

First thing I notice when looking at your definition of that option is that you seem to be confused about how to define functions. Take ifElse as an example: as you’ve written it, this is a function that accepts a single argument, which must be an attrset with the three attributes condition, resultIf, and resultElse. The way you’re using ifElse, however, is as if it accepted three arguments instead of one. To get that, you should write

ifElse = condition: resultIf: resultElse: (...);

You’ve done the same thing with lines, finalString, and possibly more; I stopped looking.

finalString in particular looks to be the cause of the error that’s being raised, as it is being passed a function (bindingCondition or blacklistCondition) when it expects an attrset.

3 Likes

Thanks, I’m a little ashamed of myself. I made the mistake in the previous test, I wasn’t sure of the syntax and should have made the change.

5, 6 corrections later, the module works perfectly.

1 Like

Don’t be; it’s not an especially helpful error message! Recent versions of Nix have improved on this front; in Nix 2.21, the error trace includes a pointer to the attrset argument of finalString, which probably would have helped you.

(Progress is possible!)

1 Like