Some nix commands not working because of overlay

Hello all,

I’m having problems to run some nix command, like for example nix-env -qa:

$ nix-env -qa torch
error: attribute 'Keras' missing, at /home/thiago/.config/nixpkgs/overlays/python_overlays.nix:10:11

I have this python overlays with the following content:

python-self: python-super:
{

  nibabel = python-super.nibabel.overrideAttrs (oldAttrs: {
    doInstallCheck = false;
    propagatedBuildInputs = oldAttrs.propagatedBuildInputs
    ++ [python-super.packaging];
  });

  Keras = python-super.Keras.overrideAttrs (oldAttrs: rec {
    pname = "Keras";
    version = "2.2.4";
    src = python-super.fetchPypi {
      pname = "Keras";
      version = "2.2.4";
      sha256 = "1j8bsqzh49vjdxy6l1k4iwax5vpjzniynyd041xjavdzvfii1dlh";
    };
  });

  plaidml = python-super.callPackage ./pkgs/plaidml {
  };

  pypubsub = python-super.callPackage ./pkgs/pubsub {
    buildPythonPackage = python-super.buildPythonPackage;
  };

  gdcm = python-super.toPythonModule ((
    python-super.callPackage ./pkgs/gdcm {
      enablePython = true;
    }).override {}) ;

  wxPython_4_1 = python-super.callPackage ./pkgs/wxPython/4.1.nix {
  };

  }

I call this python_overlays in the ~/.config/nixpkgs/overlays/overlay.nix:

self: super: {
  python3 = super.python3.override {
    packageOverrides = import ./python_overlays.nix;
  };

  python37 = super.python37.override {
    packageOverrides = import ./python_overlays.nix;
  };

  python38 = super.python38.override {
    packageOverrides = import ./python_overlays.nix;
  };
}

If comment the Keras part, it complains about other overlays in the python_overalys file. The only way is to comment all the file, so it works. It seems to me that python_overlays.nix is being evaluated directly by nix-env -qa command, not from inside the overlays.nix.

My question is: How to fix this problem?

Your overlay actually seems to work for me just fine when run against the current nixpkgs-unstable channel. I’m not installing it globally but testing against a file import <nixpkgs> { overlays = [(import ./overlay.nix)]; }, but that shouldn’t make a difference.

That said, according to the documentation you need to pass the self parameter to the override as pointing back to the python in question. I suspect this is used to ensure your override is exposed to any other package that depends on what you’re overriding. This change looks like:

self: super: rec {
  python3 = super.python3.override {
    packageOverrides = import ./python_overlays.nix;
    self = python3;
  };

  python37 = super.python37.override {
    packageOverrides = import ./python_overlays.nix;
    self = python37;
  };

  python38 = super.python38.override {
    packageOverrides = import ./python_overlays.nix;
    self = python38;
  };
}

This can be cleaned up a bit to avoid duplication:

self: super:

let overridePython = oldPython:
  let python = oldPython.override {
    packageOverrides = import ./python_overlays.nix;
    self = python;
  }; in python;
in

{
  python3 = overridePython super.python3;
  python37 = overridePython super.python37;
  python38 = overridePython super.python38;
}

Also the same documentation says you should be using overridePythonAttrs. Using overrideAttrs like you are actually means you’re not modifying the generated name attribute. You should be able to just replace your usage of overrideAttrs with .overridePythonAttrs directly.

Thanks @lilyball. The overlays were working OK here too with nixos-unstable. I applied the modifications you suggested (I tried both version) but I’m having the problem with nix-env -qa yet, see:

$ nix-env -qa torch
error: attribute 'Keras' missing, at /home/thiago/.config/nixpkgs/overlays/python_overlays.nix:10:11

I have other overlays (neovim and zettlr), they are not declared inside overlays.nix or python_overlays.nix. To test I removed both overlays and the same error happen.

What does nix-env -qaA nixpkgs.python3.pkgs.Keras say?

How about nix eval nixpkgs.python3.pkgs.Keras.name.

Also, try adding --show-trace to the nix-env call. It’s undocumented but it appears to be accepted.

$ nix-env -qaA nixpkgs.python3.pkgs.Keras
error: attribute 'nixpkgs' in selection path 'nixpkgs.python3.pkgs.Keras' not found

So I’m using nixos:

$ nix-env -qaA nixos.python3.pkgs.Keras
python3.8-Keras-2.3.1

Which is strange since in Python it show the 2.2.4:

$ python3 -c 'import keras; print(keras.__version__)'
Using Theano backend.
2.2.4

Adding the attribute name = “${pname}-${version}” to the Keras overlay it show correctly:

$ nix-env -qaA nixos.python3.pkgs.Keras
Keras-2.2.4
$ nix eval nixpkgs.python3.pkgs.Keras.name
"Keras-2.2.4"
$ nix-env --show-trace -qa torch
error: attribute 'Keras' missing, at /home/thiago/.config/nixpkgs/overlays/python_overlays.nix:10:11

Thanks again!

This is because of the use of overrideAttrs instead of overridePythonAttrs. buildPythonPackage calculates the name attribute directly instead of letting mkDerivation do it; overridePythonAttrs will ensure it calculates name using your new version attribute.


It’s a shame --show-trace apparently did nothing. You could do nix-env --debug -qa torch but that output is likely to not actually be particularly helpful. Do you have any packageOverrides declared that could be interfering? Or any unusual channels installed?

I suspect the issue is the python_overlays.nix file in $HOME/.config/nixpkgs/overlays, which is not a nixpkgs overlay, but a python.packageOverrides overlay.

All files in the overlays folder are read as nixpkgs overlays and therefore when the file python_overlays.nix is read as a nixpkgs overlay, python-self and python-super actually are self and super from nixpkgs, not python. In this case super.Keras (python-super.Keras) does not exist and raises the attribute 'Keras' missing error.

The error does not affect all nix commands, as most of them don’t evaluate the whole nixpkgs set, but only the needed values.

You should try to move the python_overlays.nix file out of the overlays folder or combine the two files into one:

self: super:
let
  packageOverrides = python-self: python-super:
    {
      nibabel = python-super.nibabel.overrideAttrs (oldAttrs: {
        doInstallCheck = false;
        propagatedBuildInputs = oldAttrs.propagatedBuildInputs
          ++ [ python-super.packaging ];
      });

      Keras = python-super.Keras.overrideAttrs (oldAttrs: rec {
        pname = "Keras";
        version = "2.2.4";
        src = python-super.fetchPypi {
          pname = "Keras";
          version = "2.2.4";
          sha256 = "1j8bsqzh49vjdxy6l1k4iwax5vpjzniynyd041xjavdzvfii1dlh";
        };
      });

      plaidml = python-super.callPackage ./pkgs/plaidml { };

      pypubsub = python-super.callPackage ./pkgs/pubsub {
        buildPythonPackage = python-super.buildPythonPackage;
      };

      gdcm = python-super.toPythonModule ((
        python-super.callPackage ./pkgs/gdcm {
          enablePython = true;
        }
      ).override { });

      wxPython_4_1 = python-super.callPackage ./pkgs/wxPython/4.1.nix { };
    };
in
{
  python3 = super.python3.override { inherit packageOverrides; };
  python37 = super.python37.override { inherit packageOverrides; };
  python38 = super.python38.override { inherit packageOverrides; };
}
1 Like

I think you are correct @B4dM4n. I moved python_overlays to the pkgs subfolder and it worked. Thanks!

Ooh I didn’t even notice that part.

The simple solution is to just nest them in a subfolder, so you have ~/.config/nixpkgs/overlays/python-overlay/ where your actual overlay is default.nix in this folder.

I just moved to inside pkgs. This the directory tree now:

$ tree --dirsfirst  overlays/
overlays/
├── pkgs
│   ├── gdcm
│   │   └── default.nix
│   ├── plaidml
│   │   └── default.nix
│   ├── pubsub
│   │   └── default.nix
│   ├── wxPython
│   │   └── 4.1.nix
│   ├── zettlr
│   │   └── default.nix
│   └── python_overlays.nix
├── neovim.nix
├── overlay.nix
└── zettlr.nix

6 directories, 9 files

The file overlay.nix (I assume that’s the one you’re using) can be moved to pkgs/default.nix (just remember to update the relative paths in it).