Skip to content

flake inputs are evaluated in place, so an input's own relative import fails pure eval #43

Description

@wyattgill9

A flake input is evaluated from its source directory rather than its store copy, so any import ./x.nix inside an input's flake.nix is an absolute out-of-store path and pure evaluation rejects it.

$ mkdir -p /tmp/dep /tmp/root

$ printf '{ hello = "world"; }\n' > /tmp/dep/lib.nix
$ printf '{\n  outputs = _: { lib = import ./lib.nix; };\n}\n' > /tmp/dep/flake.nix
$ printf '{\n  inputs.dep.url = "path:/tmp/dep";\n  outputs = { dep, ... }: { value = dep.lib.hello; };\n}\n' > /tmp/root/flake.nix

$ cd /tmp/root

$ nix eval .#value
"world"

$ fix eval --extra-experimental-features flakes --flake '.#value'
error: access to absolute path '/tmp/dep/lib.nix' is forbidden in pure evaluation mode (use --impure to allow)

trace:
note: while evaluating 'outputs.lib' at /tmp/dep/flake.nix:2:24
   2 |   outputs = _: { lib = import ./lib.nix; };
     |                        ^^^^^^^^^^^^^^^^

$ fix eval --extra-experimental-features flakes --impure --flake '.#value'
"world"

Nix copies each input to the store and evaluates its flake.nix from there, so ./lib.nix resolves under /nix/store/…-source and is allowed in pure mode. fix evaluates the input in place, so the same import is a plain absolute path and the pure-eval check fires.

The store copy is not missing, only unused by evaluation. A tarball input shows both halves in one run — the fetch is stored, and the eval still reads the cache directory:

$ fix build --flake '.#' --extra-experimental-features flakes    # a flake-parts flake
[     115ms] [fetch] cached https://codeload.github.com/hercules-ci/flake-parts/tar.gz/17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e
[     124ms] [daemon] stored /nix/store/xfg4bws749i95jvnxhymxmfwailzk38q-source
…
error: input 1 derivation selection failed: RestrictedInPureEval

$ fix eval --extra-experimental-features flakes --flake '.#packages.aarch64-darwin.default'
error: access to absolute path '/Users/…/.cache/fix/tarball/15646a24e94e42e737ce3a363972a4d7/source/lib.nix' is forbidden in pure evaluation mode (use --impure to allow)

trace:
note: while evaluating 'outputs.lib' at /Users/…/.cache/fix/tarball/15646a24e94e42e737ce3a363972a4d7/source/flake.nix:10:13
  10 |       lib = import ./lib.nix {
     |             ^^^^^^^^^^^^^^^^^^

Splitting a flake across a couple of files is ordinary — flake-parts does it, so every flake built on flake-parts hits this — and a --flake installable is pure by default, so eval, build and instantiate all fail on such a flake unless --impure is passed, which is a poor trade for a CI check.

Two smaller things fall out of the same run. build reports the restriction as error: input 1 derivation selection failed: RestrictedInPureEval with no path, no trace and no mention of --impure, so the cause is only visible by re-running under eval. And fix flake check evaluates the same flake-parts flake to checked 14 flake output(s): ok, so it is not applying the pure-eval restriction that --flake installables apply.


fix 0.3.0, release binary fix-v0.3.0-aarch64-darwin.tar.gz, darwin/aarch64. Reference implementation is Nix 2.34.8.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions