The papercut thread - post your small annoyances/confusions here

It could just be because I’m doing it wrong, but nix search something doesn’t really work for me, I’ll always have to resort to nix-env -qaP .*something.* to get results.


People should use

let {mkOption, mkEnableOption} = lib;
in ...

Instead of with lib; so I have the slightest chance to figure out what the hell is going on in code…

Honestly I wish we’d delete the with statement from the language. It’s pure evil in terms of readability. Also it delays usage of undefined variables further down in evaluation time, giving more obscure errors.


Wait, do we have destructuring in the language like that?


I’m surprised as well, It add much more clearness, I like it…but does it work? It seems not to in the repl, I’ll try in a standalone file

There is let inherit (lib) mkOption mkEnableOption; in, which does the same.


Here is a fully expanded example

# Feature simmilar to `let {mkOption, mkEnableOption} = lib;
  nixpkgs = import <nixpkgs> {};
in {
  example = let
    inherit (nixpkgs.lib) mkOption mkEnableOption;
  in [mkOption mkEnableOption];

Oh maybe we don’t. But we maybe we should!?

We have it in lambas, why not in let’s?

1 Like

These might be off topic for being too significant:

  • “Cannot coerce set to string”, and company being utterly useless for finding where the actually problem occurred in a string. There was a dead pull requests but I can’t find it.
  • better infinite recursion debugging
  • No consistent debugging interface. I want to just slap a function around any sufficiently advanced derivation and get it full stack debuggable with GDB or whatever. (may be reasonable to extend to other functionality)
  • fetchgit silently breaks .git, well, by design

Some more from my sticky notes, a lot of these seem controversial. or I’m just missing something:

  • I can’t stick NIX_DEBUG=1 on nix-build I have to put it in the expression somewhere

  • There is no trivial one-liner way to drop into a mutable build shell when a build fails (though maybe cntr alleviates this a bit)

  • The python calling conventions for nix-shell -p are weird and don’t work for some variations but do for others (???) (sticky note says: nix shell with python and a list of packages, not pythonWithPackages and why this breaks)

  • posix man pages are not installed by default

  • zsh: no such file or directory: ./ and company, for un-patchelfed binaries or whatever are severely misleading for new users

  • I can never remember the patchelf flags, is it just me or are they weird

  • language infrastructures that use something other than overrideAttrs

  • people use a lot of let expressions, which makes sense, but how can that be consolidated with wanting to override things?

  • more things that I guess I didn’t write down separately and would have to find in IRC logs…


That looks like the same issue as

I would certainly be in favour, especially if it could accelerate the death of with by providing a better mechanism for the common usecase :slight_smile:

Maybe you could draft an RFC?

Edit: Actually, maybe the let inherit approach could be sufficient? I’ll have to think about this…

1 Like

Python package overlays don’t compose, because they need to use an explicit packageOverrides.

There’s a discussion about it here: Python's packageOverrides isn't composible · Issue #44426 · NixOS/nixpkgs · GitHub

But it doesn’t align with what you would expect using other overlays for system packages. :frowning:

Current workaround seem to be: Use lib.composeExtensions with previous packageOverrides.


I can’t tell when and if I should use nix build -f default.nix test
instead of nix-build -A test.

The nix repl is useful for iterating on derivations, but nix-shell
is simpler to launch a one-off command.

I haven’t found guidelines on their usage other than Eelco’s
presentation of the initial nix CLI in 2015 NixCon 0.


The output of a nix/os command should never be empty. Ever. What does it mean if a command takes 30 seconds to run and returns nothing? It’s incredibly context-dependent. Sometimes it means success, other times it means it has no idea what you’re talking about.

Seems like such a simple fix.


I filed an issue about this already, but the documentation does a very bad job of explaining that syntax.


Here’s my biggest pet peeve (other than the with keyword as mentioned above):

Sometimes I’m writing a derivation and realize I may need to use propagatedBuildInputs instead of the normal buildInputs. I have a vague understanding that propagatedBuildInputs will “propagate” those build inputs, but I don’t really know what’s going on, so I google for the difference.

I normally find the following section in the nixpkgs manual:

I try to read this section, get completely lost about half way through, give up, and go back to just randomly trying propagatedBuildInputs or buildInputs until something seems to work.

I think the explanation for how propagation works is too detailed for a user manual. I think the first thing in that section should really just be a couple examples of when propagatedBuildInputs is needed and not needed. I think the detailed explanation of exactly how dependencies are propagated and in what way should be saved for a different document. Maybe a wiki page?


And, oh, please, stop littering my tree with ./result* symlinks :wink: . The worst being nixos-rebuild build, which pins a whole system in whatever location you happen to be.


Running man nix on NixOS gives me

No manual entry for nix

While nix --help works.


12 posts were split to a new topic: Documentation improvements

I think it is sufficient! I think we should heavily document this; it seems very useful!!

Example usage that I am now using in a module I’m building

{ lib, config, ...}: 
  inherit (lib) mkIf mkMerge mkOption mkEnableOption ;
  inherit (lib.types) attrsOf str;
{ = {
    enable = mkEnableOption "journal-upload";
    config = mkOption {
      type = attrsOf str;

  }; = {
    enable = mkEnableOption "journal-remote";
    config = mkOption {
      type = attrsOf str;

  config = mkMerge [

    (mkIf config.journal-upload.enable {
      systemd.sockets.systemd-journal-upload.wantedBy = [ ""];
      environment.etc."journal-upload.conf".text = "";

    (mkIf config.journal-remote.enable {
      systemd.sockets.systemd-journal-remote.wantedBy = [ ""];
      environment.etc."journal-remote.conf".text = "";


I have a lot of trouble finding the definitions of particular functions.

I have a lot of trouble with having to cleanroom a compiler toolchain (Rust in this case) when the version I want to use isn’t in nixpkgs.

Several compiler toolchains (again, Rust) depend on the auto-updater (rustup) instead of on a precise .tar.gz.

(I know I should really get involved with the Rust derivation maintenance, or at least talk to the people involved to understand the philosophy.)