jdx/mise · error

nix failed: Nix bootstrap requires modern `nix profile`…

Error message

nix {} failed: {}
Nix bootstrap requires modern `nix profile` support and the nix-command and flakes experimental features. Enable these in your Nix configuration; mise does not change it.

What it means

mise runs read-only `nix` queries (e.g. `nix config show --json`, `nix profile list --json`, `nix eval --json ...`) through `query()`. When the nix subprocess exits non-zero, mise wraps the captured stderr in this message pointing at the two usual root causes: missing modern `nix profile` support and disabled experimental features (`nix-command`, `flakes`). mise deliberately does not mutate the user's Nix configuration.

Solutions

  1. Enable the experimental features: add `experimental-features = nix-command flakes` to `~/.config/nix/nix.conf` (or `/etc/nix/nix.conf`).
  2. Upgrade Nix to 2.24+ so modern `nix profile` exists.
  3. Run the failing command shown in the message manually to see the underlying Nix diagnostic.
  4. If `nix eval --offline` fails on registry lookups, warm the registry cache once online or use explicit flake URLs instead of registry names.
  5. Check NIX_CONFIG / nix.conf in CI images; the environment mise runs in may differ from your shell.

Example fix

# before (nix.conf)
# (no experimental-features line)

# after
experimental-features = nix-command flakes
Defensive patterns

Strategy: validation

Validate before calling

# ensure features before relying on nix-backed installs
grep -q 'experimental-features' ~/.config/nix/nix.conf || \
  echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf
nix --version # require >= 2.24

Try / catch

async fn run_query(args: &[&str]) -> Result<String> {
    query(args).await.map_err(|e| {
        eprintln!("hint: enable nix-command and flakes, upgrade Nix >= 2.24");
        e
    })
}

Prevention

When it happens

Trigger: Any `nix` invocation in `query()` fails: experimental features not enabled (`nix-command`/`flakes`), no `nix profile` support (very old Nix), bad profile path, registry resolution failure, or `nix eval --impure` disallowed by config.

Common situations: Fresh Nix installs without `experimental-features = nix-command flakes` in nix.conf; single-user Nix on distros with ancient versions; sandboxed CI where nix.conf is not the user's; `--offline` eval failing due to missing flake registry cache.

Understand the failure class

Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/0234806f0e7298c1. Report an issue: GitHub.

Appendix: source

Thrown at src/system/packages/nix.rs:137

    refs: Vec<Value>,
}

#[derive(Clone)]
struct MatchedEntry {
    name: String,
    paths: Vec<String>,
}

async fn query(args: &[&str]) -> Result<String> {
    debug!("$ nix {}", shell_words::join(args));
    let output = tokio::process::Command::new("nix")
        .args(args)
        .stdin(Stdio::null())
        .output()
        .await
        .wrap_err("failed to run Nix; install Nix and make its CLI available on PATH")?;
    if !output.status.success() {
        bail!(
            "nix {} failed: {}\nNix bootstrap requires modern `nix profile` support and the nix-command and flakes experimental features. Enable these in your Nix configuration; mise does not change it.",
            shell_words::join(args),
            String::from_utf8_lossy(&output.stderr).trim()
        );
    }
    Ok(String::from_utf8(output.stdout)?)
}

/// Passing an explicit profile avoids Nix's default-profile initialization:
/// even `nix profile list` otherwise creates ~/.nix-profile on a fresh home.
async fn profile_path() -> Result<PathBuf> {
    let config: Value = serde_json::from_str(&query(&["config", "show", "--json"]).await?)?;
    let xdg = config["use-xdg-base-directories"]["value"]
        .as_bool()
        .unwrap_or(false);
    Ok(if xdg {
        std::env::var_os("XDG_STATE_HOME")
            .filter(|p| !p.is_empty())

View on GitHub (pinned to 533346cc37)