You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

导入nixpkgs使用flake overlays的attrValues报autoslot属性缺失错误

问题现象

使用attrValues overlays.overlays批量向nixpkgs传入overlay配置时运行失败,抛出错误error: attribute 'autoslot' missing;手动枚举overlay组成列表传入时可正常运行,相关配置如下:

{
    description = "Shared settings for our packages!";
    inputs = {
        nixpkgs.url = github:NixOS/nixpkgs/nixos-22.05;
        flake-utils.url = github:numtide/flake-utils;
        flake-compat = {
            url = "github:edolstra/flake-compat";
            flake = false;
        };
    };
    outputs = inputs@{ self, nixpkgs, flake-utils, ... }: with builtins; with flake-utils.lib; let
        lib = import ./package.nix nixpkgs;
        overlays = with lib; rec {
            overlays = let
                lib-overlay = import ./overlay.nix nixpkgs;
            in j.foldToSet' [
                {
                    lib = lib-overlay;
                    default = lib-overlay;
                }
                (j.imports.overlaySet {
                    dir = ./callPackages/python2;
                    func = file: final: prev: j.update.python.callPython.two final prev file;
                })
                (j.imports.overlaySet {
                    dir = ./callPackages/python3;
                    func = file: final: prev: j.update.python.callPython.three final prev file;
                })
                (j.imports.set { dir = ./overlays; recursive = true; ignores.dirs = true; })
                (j.imports.overlaySet { dir = ./callPackages; call = 1; })
            ];
            overlay = overlays.default;
            defaultOverlay = overlay;
        };
        make = system: with lib; rec {

            # 该写法无法正常运行
            legacyPackages = import nixpkgs { inherit system; overlays = attrValues overlays.overlays; };

            # 该写法可正常运行
            legacyPackages = import nixpkgs { inherit system; overlays = with overlays.overlays; [ overlays.overlays.lib Python autoslot ]; };

            # 问题追踪位置
            packages = flattenTree (let _ = j.filters.has.attrs legacyPackages (unique (flatten [
                (subtractLists (attrNames nixpkgs.legacyPackages.${system}) (attrNames legacyPackages))
                (attrNames overlays.overlays)
            ])); in trace (attrNames legacyPackages.Python.pkgs.autoslot) _);

            package = packages.default;
            defaultPackage = package;
            apps.default = settings.make.app package;
            app = apps.default;
            defaultApp = app;
            devShells.default = import ./devShell.nix system self;
            devShell = devShells.default;
            defaultdevShell = devShell;
        };
    in (eachSystem allSystems make) // overlays // { inherit lib; };
}
问题原因
  • overlay加载顺序不符合依赖要求:builtins.attrValues返回的属性值列表默认按属性名字典序排序,和手动枚举的lib -> Python -> autoslot顺序不一致。autoslot是Python相关overlay提供的依赖项,当依赖autoslot的overlay先于提供autoslot的overlay加载时,就会触发属性缺失错误。
  • 混入冗余别名项:overlays.overlays集合内定义了default/overlay/defaultOverlay这类自引用别名,attrValues会把这些重复指向同一个overlay的别名项也加入加载列表,重复加载会打乱属性覆盖逻辑,进一步放大顺序问题。
解决方案
  • 存在跨overlay依赖的场景,不要直接用attrValues批量取值,显式按依赖顺序指定加载列表:
    # 按依赖优先级从高到低排列overlay名称,被依赖的项放在前面
    overlayLoadOrder = [ "lib" "Python" "autoslot" /* 其余overlay按依赖顺序补全 */ ];
    loadedOverlays = builtins.map (name: overlays.overlays.${name}) overlayLoadOrder;
    legacyPackages = import nixpkgs { inherit system; overlays = loadedOverlays; };
    
  • 调整overlay集合的结构,把实际生效的overlay和对外暴露的别名拆分存储,避免attrValues取到冗余项:
    overlays = with lib; rec {
      # 仅存储实际需要加载的overlay,不要在这个集合里放default/overlay这类别名
      runtimeOverlays = j.foldToSet' [
        { lib = lib-overlay; }
        (j.imports.overlaySet { dir = ./callPackages/python2; /* 其余配置保持不变 */ })
        (j.imports.overlaySet { dir = ./callPackages/python3; /* 其余配置保持不变 */ })
        (j.imports.set { dir = ./overlays; recursive = true; ignores.dirs = true; })
        (j.imports.overlaySet { dir = ./callPackages; call = 1; })
      ];
      # 对外暴露的别名单独定义,不混入实际加载的overlay集合
      overlay = runtimeOverlays.lib;
      defaultOverlay = overlay;
      overlays = runtimeOverlays // { default = overlay; };
    };
    
    如果拆分后所有overlay之间没有依赖关系,可以直接用attrValues overlays.runtimeOverlays传入;如果存在跨依赖,还是需要按上一种方法显式指定加载顺序。
  • 顺序排查技巧:在传入nixpkgs前打印实际加载的overlay列表,和正常运行的枚举顺序对比调整即可:
    overlays = builtins.trace (builtins.map (o: o.meta.name or "unnamed-overlay") overlaysToLoad) overlaysToLoad;
    

内容的提问来源于stack exchange,提问作者syvlorg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 19:42:14