Skip to content

Conversation

@langsjo
Copy link
Contributor

@langsjo langsjo commented Jul 17, 2025

Resolves #425858

This commit makes derivations built with stdenv.mkDerivation have an assert that ensures env is a non-derivation attrset.

Also drops a test that expects the behavior this PR is disallowing to be allowed.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • Nixpkgs 25.11 Release Notes (or backporting 25.05 Nixpkgs Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
  • NixOS 25.11 Release Notes (or backporting 25.05 NixOS Release notes)
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md, pkgs/README.md, maintainers/README.md and other contributing documentation in corresponding paths.

Add a 👍 reaction to pull requests you find important.

@emilazy
Copy link
Member

emilazy commented Jul 17, 2025

How did a non-attribute set env behave prior to that PR?

cc @wolfgangwalther @ShamrockLee for structured attrs concerns

@nixpkgs-ci nixpkgs-ci bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 0 This PR does not cause any packages to rebuild on Linux. 6.topic: stdenv Standard environment labels Jul 17, 2025
@langsjo
Copy link
Contributor Author

langsjo commented Jul 17, 2025

How did a non-attribute set env behave prior to that PR?

It would pass evaluation and build without issue if __structuredAttrs was set to false, otherwise it would fail evaluation on an assert with message "When using structured attributes, env must be an attribute set of environment variables."

@philiptaron
Copy link
Contributor

Wow, this is pretty screwy. Maybe it's a kneejerk reaction, I feel like this PR is going in the wrong direction: how can we enforce env being an attrset more broadly instead of only when __structuredAttrs is set?

Reading the linked issue, I saw that @eclairevoyant gave it a 👍🏻 -- maybe you or they could say more about the cases that led to this PR? Is there a derivation (whether in nixpkgs or not) that uses env as non-attrs?

@emilazy
Copy link
Member

emilazy commented Jul 17, 2025

Right, but I mean what would it do? Create an environment variable called env? Since we're hoping to turn structured attributes on by default at some point and you can always env.env = ...;, maybe we should just mandate it be an attribute set always. But I don't want to block a fix of a simple regression so this is purely a drive-by comment.

@langsjo
Copy link
Contributor Author

langsjo commented Jul 17, 2025

AFAICT, if env was something that can get coerced to a string, such as an integer, a string, a derivation, a list of things that can get coerced into strings, and probably more, it would set the environment variable env to whatever the result of that string coercion was. If it could not get coerced to a string (such as a function, list containing an attrset, and probably more), it would fail with an error such as this (full trace)

nix-build -E "(import ./. {}).callPackage ./test.nix {}" --show-trace
error:
       … while calling the 'derivationStrict' builtin
         at <nix/derivation-internal.nix>:37:12:
           36|
           37|   strict = derivationStrict drvAttrs;
             |            ^
           38|

       … while evaluating derivation 'test-0.0.0'
         whose name attribute is located at /home/langsjo/git/nixpkgs/pkgs/stdenv/generic/make-derivation.nix:468:13while evaluating attribute 'env' of derivation 'test-0.0.0'
         at /home/langsjo/git/nixpkgs/test.nix:28:3:
           27|
           28|   env = lib.map;
             |   ^
           29|

       error: cannot coerce the built-in function 'map' to a string: «primop map»

@langsjo
Copy link
Contributor Author

langsjo commented Jul 17, 2025

maybe you or they could say more about the cases that led to this PR? Is there a derivation (whether in nixpkgs or not) that uses env as non-attrs?

There was a bug in one of llama.cpp's nix file spotted by @amozeo, where they use lib.optionals to optionally set the value of env to an attrset. If the condition was true, it would work fine and pass the attrset, but if it was false, it would set it to an empty list. This very likely was unintentional, but it got me to look at stdenv and found that there was some regression.

I do think that making env throw when not an attrset makes sense, but didn't think that I had enough knowledge to make that decision, so opened this PR instead.

@philiptaron
Copy link
Contributor

philiptaron commented Jul 17, 2025

I do think that making env throw when not an attrset makes sense, but didn't think that I had enough knowledge to make that decision, so opened this PR instead.

I think I'm gutsy enough to merge that PR now.

There was a bug in one of llama.cpp's nix files

Yeah -- I think either I or @SomeoneSerge wrote that bug 😳 Thanks for the real-life example. I do have commit rights over there and I have let the derivation rot somewhat so please tag me on the PR to fix.

Copy link
Contributor

@philiptaron philiptaron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to merge a more decisive PR that doesn't allow env to be anything other than an attrset.

@github-project-automation github-project-automation bot moved this to In Progress in Stdenv Jul 17, 2025
@langsjo

This comment was marked as outdated.

@langsjo langsjo changed the title stdenv: add isAttrs check on env before passing it to // operator stdenv: assert that env is an attrset Jul 17, 2025
@langsjo langsjo marked this pull request as draft July 17, 2025 22:54
@langsjo
Copy link
Contributor Author

langsjo commented Jul 17, 2025

@philiptaron there are some Ruby packages which have a pattern of env = bundlerEnv { ... }, which creates a derivation (which is why the nixpkgs-vet check failed). Don't know anything about Ruby, but seems that they just used env as the name of a variable, not to create env vars. Changing the name from env to something else fixed it and the derivations build. Should I add another commit making this change to those packages?

@roberth
Copy link
Member

roberth commented Jul 17, 2025

but I mean what would it do? Create an environment variable called env?

Pretty much. env was introduced with an overabundance of caution. In the limit, taking any name out of an open attrset and repurposing it is a breaking change. Unfortunately the mkDerivation argument is both a dict and a record as in https://nix.dev/manual/nix/2.28/development/json-guideline#extensibility. That should have never happened, but otoh environment variables have aspects of both too, so all software is screwed :D (EDIT: unix software, I mean. Hot take, I know)

Copy link
Member

@emilazy emilazy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this approach.

@emilazy
Copy link
Member

emilazy commented Jul 17, 2025

@philiptaron there are some Ruby packages which have a pattern of env = bundlerEnv { ... }, which creates a derivation (which is why the nixpkgs-vet check failed). Don't know anything about Ruby, but seems that they just used env as the name of a variable, not to create env vars. Changing the name from env to something else fixed it and the derivations build. Should I add another commit making this change to those packages?

Yeah, let’s fix those. It would have to be done when we turn on structured attributes by default anyway. Looks like rubyEnv, gemEnv, deps are all used.

This does mean that this is probably a breaking change for out‐of‐tree users, but the fix is trivial enough that I think it’s okay.

@emilazy
Copy link
Member

emilazy commented Jul 17, 2025

@wolfgangwalther Any idea why https://github.com/NixOS/nixpkgs/actions/runs/16358006170/job/46220573630?pr=426211 is unhappy but the eval CI passed, by the way?

@nixpkgs-ci nixpkgs-ci bot added 12.approvals: 2 This PR was reviewed and approved by two persons. and removed 12.approvals: 1 This PR was reviewed and approved by one person. labels Jul 18, 2025
@ShamrockLee
Copy link
Contributor

ShamrockLee commented Jul 18, 2025

Thanks for pinning.

How did a non-attribute set env behave prior to that PR?

Aside from how env influences the result derivation arguments, we should also inspect how it behave in <pkg>.overrideAttrs.

Update:

Perhaps we need some more tests inside tests.overriding to guard those features.

@emilazy
Copy link
Member

emilazy commented Jul 18, 2025

This error happened in pkgs/by-name/ev/evil-winrm/package.nix. This package is a by-name package, so nixpkgs-vet checks it. But this package doesn't have meta.platforms set, so hydra won't build it - thus we don't eval it either.

Hydra does build packages with no meta.platforms. If the CI eval mismatches that it's a bug.

@wolfgangwalther
Copy link
Contributor

Hydra does build packages with no meta.platforms. If the CI eval mismatches that it's a bug.

OK, I will look into that. In any case, this is an existing issue, not caused by this PR at all. I have seen this for quite a while already. I remember reading somewhere that hydra needs meta.platforms and thus concluded this to be the case. But apparently that's not true and these packages (without meta platform) are lost somewhere else along the way.

@wolfgangwalther
Copy link
Contributor

Hydra does build packages with no meta.platforms. If the CI eval mismatches that it's a bug.

OK, I will look into that. In any case, this is an existing issue, not caused by this PR at all. I have seen this for quite a while already. I remember reading somewhere that hydra needs meta.platforms and thus concluded this to be the case. But apparently that's not true and these packages (without meta platform) are lost somewhere else along the way.

Scratch that:

  • Packages without meta.platform seem to work the same way as others regarding Eval, according to my tests right now.
  • The same kind of assertion error is also not caught by eval, when it's on a package that has meta platform listed (I tested ronn, which was changed in this PR, too).

What happens once an assertion fails: The package is removed from the listed attrpaths already. That's the first step of eval, calling release-attrpaths-superset.nix.

I will have to test more, but I think assert might in general not be caught by Eval.

@wolfgangwalther
Copy link
Contributor

wolfgangwalther commented Jul 18, 2025

I will have to test more, but I think assert might in general not be caught by Eval.

It's essentially this already known issue: #397184 (comment)

Edit: Also note my conclusion in #397184 (comment).

Copy link
Member

@roberth roberth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, although I'm banking on the other reviews a bit for the details.
Nice to get rid of the unnecessary environment variable, thanks!

@nixpkgs-ci nixpkgs-ci bot added 12.approvals: 3+ This PR was reviewed and approved by three or more persons. and removed 12.approvals: 2 This PR was reviewed and approved by two persons. labels Jul 18, 2025
@langsjo langsjo force-pushed the stdenv-fix branch 2 times, most recently from c92adf6 to b937eac Compare July 18, 2025 17:41
langsjo added 6 commits July 18, 2025 11:21
`env` is now only allowed to be an attribute set in `stdenv.mkDerivation`
`env` is now only allowed to be an attribute set in `stdenv.mkDerivation`
`env` is now only allowed to be an attribute set in `stdenv.mkDerivation`
`env` is now only allowed to be an attribute set in `stdenv.mkDerivation`
This behavior is no longer supported
@philiptaron
Copy link
Contributor

Rebased on master due to CI failure that looked like a GitHub actions issue.

@philiptaron philiptaron merged commit e0327a1 into NixOS:master Jul 18, 2025
24 of 27 checks passed
@github-project-automation github-project-automation bot moved this from In Progress to Done in Stdenv Jul 18, 2025
@langsjo langsjo deleted the stdenv-fix branch July 20, 2025 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: stdenv Standard environment 8.has: changelog This PR adds or changes release notes 8.has: documentation This PR adds or changes documentation 10.rebuild-darwin: 11-100 This PR causes between 11 and 100 packages to rebuild on Darwin. 10.rebuild-linux: 11-100 This PR causes between 11 and 100 packages to rebuild on Linux. 12.approvals: 3+ This PR was reviewed and approved by three or more persons.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

stdenv: derivation evaluation fails when 'env' is not an attrset

6 participants