Nix: error: '/nix/store/.../flake.nix' must be an attribute set

Created on 28 Aug 2020  ·  6Comments  ·  Source: NixOS/nix

Describe the bug

This flake.nix evaluates to an attribute set:

let
  foo = "bar";
in
{
  outputs = { self, nixpkgs }:
    {
      packages.x86_64-linux.devShell = nixpkgs.outputs.legacyPackages.x86_64-linux.hello;
    };
}

however nix develop (or nix build .#devShell) results in the following error:

$ nix develop
error: --- Error ------------------------------------------------------------------------------------ nix
file '/nix/store/wvlsr8s3nysj0pmgdl7ndggpxc8za87f-source/flake.nix' must be an attribute set
(use '--show-trace' to show detailed location information)

I can make nix happy by moving the let inside the outputs definition:

{
  outputs = { self, nixpkgs }:
    let
      foo = "bar";
    in
      {
        packages.x86_64-linux.devShell = nixpkgs.outputs.legacyPackages.x86_64-linux.hello;
      };
}

Expected behavior

I'm expecting the flake commands to allow top-level let bindings; but maybe that's on purpose to ensure the flake.nix stays as simple as possible?

nix-env --version output

nix-env (Nix) 2.4pre20200721_ff314f1

bug

Most helpful comment

Why then use nix syntax if it is not nix? I'd say, either use a clearly defined subset of nix code, at best with another name and file ending (tnix – total nix) or the flake file shall be in a total language like plain json and the outputs attr refers to nix expressions, or dhall (but a comparatively complex new language).

If it looks like nix but isn't, to me it is confusing unexpected (”strange“ – zimbatm) behaviour.

Edit: Why not split the flake.nix into flake.json containing metadata and inputs and flake.nix/outputs.nix containing only the outputs function in real Nix lang?

All 6 comments

That's a strange limitation of how flakes are being evaluated. All of the data structures must be pretty much JSON-like data. The only place where more complex nix code is allowed is within the outputs function.

but maybe that's on purpose to ensure the flake.nix stays as simple as possible?

That's right. It ensures that a command like nix flake info doesn't have to evaluate an arbitrarily complex (and possibly non-terminating) Nix expression.

Ok I realize it's actually terribly picky, even thunks are forbidden (i.e. in an input's { url = "foo" + "bar"; }):

/tmp/tmp.7jJ3XRKbVP$ nix develop
error: --- Error ------------------------------------------------------------------------------------- nix
expected a string but got a thunk at /nix/store/4yiaxz02925lr1ssyir8nc7cs8dp7bf0-source/flake.nix:2:3
(use '--show-trace' to show detailed location information)

Why then use nix syntax if it is not nix? I'd say, either use a clearly defined subset of nix code, at best with another name and file ending (tnix – total nix) or the flake file shall be in a total language like plain json and the outputs attr refers to nix expressions, or dhall (but a comparatively complex new language).

If it looks like nix but isn't, to me it is confusing unexpected (”strange“ – zimbatm) behaviour.

Edit: Why not split the flake.nix into flake.json containing metadata and inputs and flake.nix/outputs.nix containing only the outputs function in real Nix lang?

I like the idea of specifying inputs and metadata in json. It's easier to work with for Nix itself and for external tools. With niv I often use niv update some-input -b feature-branch to test things out. nix flake doesn't have such a command and it'd be relatively hard to implement given the current flake format, because we don't have a way to write back modified asts without touching unmodified whitespace and comments.

I always used to think of the Nix language as a predictable element in an otherwise messy domain. Just a lazy evaluator that implicitly writes derivations. I don't think flakes need to change that.

I like the idea of specifying inputs and metadata in json.

The configs branch adds support for TOML as an alternative to flake.nix (1dc3f5355a3786cab37a4de98ca46a859e015d89). This allows the flake to be modified from the command line (e.g. 3632593bfc2daa82b2527c601604c8d9ae91840e).

nix flake doesn't have such a command

Well there is the --override-input flag. Since it only overwrites the lock file it doesn't have to deal with rewriting Nix expressions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

luc65r picture luc65r  ·  3Comments

dasJ picture dasJ  ·  3Comments

Infinisil picture Infinisil  ·  3Comments

bennofs picture bennofs  ·  3Comments

vaibhavsagar picture vaibhavsagar  ·  3Comments