Import fails despite correct (?) relative path

My flake has the following structure, simplified to highlight the relevant files.

.flake/
├── flake.lock
├── flake.nix
├── host
│   ├── _modules
│   │   ├── stylix.nix
│   │   └── ...
│   ├── hostA
│   │   └── ...
│   └── hostB
│       └── ...
├── theme
│   └── default.nix
└── user
    ├── _modules
    │   ├── stylix.nix
    │   └── ...
    ├── userA
    │   └── ...
    └── userB
        └── ...

To ensure consistent theming of system / home-manager, each stylix.nix file merely imports the common configuration at theme/default.nix:

{ config, lib, pkgs, ... }:

{
  imports = [
    ../../theme
  ];
}

This results in an immediate build error

error: access to absolute path '/nix/store/theme' is forbidden in pure evaluation mode (use '--impure' to override)

If I move the theme folder one level down (into both user and host) and change the imports to ../theme the flake builds without error.

For some reason, when I try to reference the root folder of the flake, nix suddenly thinks I’m escaping the flake. Why might this be?

Feel free to inspect the flake… It’s unfinished but was working fine before this change.

I would look for a place you’re accidentally copying subdirs of your flake to the nix store as independent objects. This happens, for example, if you use a path-type inside an antiquote.

Yes, that was it! Chatting with AI yielded the same advice just before I saw your reply. The simple fix is here.

But since it was not (at all!) obvious to me and may be a trap that others land in… here is the more detailed explanation (courtesy Gemini 3 Pro):

-–

Somewhere in your flake.nix (or wherever you import host), you are likely referencing the host directory using string interpolation (quotes) or a function that converts a path to a string.

Look for a line that looks like this:

# BAD: This breaks relative imports
modules = [
  "${./host}/hostA/configuration.nix" 
];

Why this fails

  1. When you wrap a path in quotes "${./host}...", Nix immediately copies only that directory (./host) to the Nix store (e.g., resulting in /nix/store/abc...-host).

  2. Your stylix.nix is now living inside this isolated store path.

  3. When stylix.nix tries to import ../../theme:

    • One .. goes to the root of the isolated store path (/nix/store/abc...-host).

    • The next .. (from ../../theme) attempts to traverse out of the store path, landing in /nix/store.

    • It then looks for theme, resulting in /nix/store/theme.

  4. Since /nix/store/theme does not exist (and is an absolute path forbidden in pure mode), the build fails.

The Fix

You must pass the path as a path literal so Nix understands it is part of the larger flake source tree.

1 Like

A surprisingly good explanation, for AI. Glad you found it.