From 366e3eff8c1e15441f2a318fe68795bd0f9f5b2d Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Thu, 11 Jun 2026 12:22:41 +0200 Subject: [PATCH 1/8] stdenv/meta: move remediation messages into different file This unclutters the file a little and makes it easier to pass them all on as a collection. This will be helpful in the migration from check into meta.problems where we generally want to emit the (almost) identical error and retain all the remediation information without duplicating the text. --- pkgs/stdenv/generic/check-meta.nix | 112 ++------------------------- pkgs/stdenv/generic/remediation.nix | 114 ++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 105 deletions(-) create mode 100644 pkgs/stdenv/generic/remediation.nix diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index 70c009c3e83ae..25ecf31372f3b 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -11,8 +11,6 @@ let all attrValues concatMapStrings - concatStrings - filter findFirst getName length @@ -46,6 +44,13 @@ let getEnv ; + inherit (import ./remediation.nix { inherit lib; }) + remediateOutputsToInstall + remediate_insecure + remediate_allowlist + remediate_predicate + ; + inherit (import ./problems.nix { inherit lib; }) problemsType genCheckProblems @@ -195,109 +200,6 @@ let showSourceType = showLicenseOrSourceType; pos_str = meta: meta.position or "«unknown-file»"; - - remediation_env_var = - allow_attr: - { - Unfree = "NIXPKGS_ALLOW_UNFREE"; - UnsupportedSystem = "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM"; - NonSource = "NIXPKGS_ALLOW_NONSOURCE"; - } - .${allow_attr}; - remediation_phrase = - allow_attr: - { - Unfree = "unfree packages"; - UnsupportedSystem = "packages that are unsupported for this system"; - NonSource = "packages not built from source"; - } - .${allow_attr}; - remediate_predicate = predicateConfigAttr: attrs: '' - - Alternatively you can configure a predicate to allow specific packages: - { nixpkgs.config.${predicateConfigAttr} = pkg: builtins.elem (lib.getName pkg) [ - "${getName attrs}" - ]; - } - ''; - - # flakeNote will be printed in the remediation messages below. - flakeNote = " - Note: When using `nix shell`, `nix build`, `nix develop`, etc with a flake, - then pass `--impure` in order to allow use of environment variables. - "; - - remediate_allowlist = allow_attr: rebuild_amendment: '' - a) To temporarily allow ${remediation_phrase allow_attr}, you can use an environment variable - for a single invocation of the nix tools. - - $ export ${remediation_env_var allow_attr}=1 - ${flakeNote} - b) For `nixos-rebuild` you can set - { nixpkgs.config.allow${allow_attr} = true; } - in configuration.nix to override this. - ${rebuild_amendment} - c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add - { allow${allow_attr} = true; } - to ~/.config/nixpkgs/config.nix. - ''; - - remediate_insecure = - attrs: - '' - - Known issues: - '' - + (concatStrings (map (issue: " - ${issue}\n") attrs.meta.knownVulnerabilities)) - + '' - - You can install it anyway by allowing this package, using the - following methods: - - a) To temporarily allow all insecure packages, you can use an environment - variable for a single invocation of the nix tools: - - $ export NIXPKGS_ALLOW_INSECURE=1 - ${flakeNote} - b) for `nixos-rebuild` you can add ‘${getNameWithVersion attrs}’ to - `nixpkgs.config.permittedInsecurePackages` in the configuration.nix, - like so: - - { - nixpkgs.config.permittedInsecurePackages = [ - "${getNameWithVersion attrs}" - ]; - } - - c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add - ‘${getNameWithVersion attrs}’ to `permittedInsecurePackages` in - ~/.config/nixpkgs/config.nix, like so: - - { - permittedInsecurePackages = [ - "${getNameWithVersion attrs}" - ]; - } - - ''; - - remediateOutputsToInstall = - attrs: - let - expectedOutputs = attrs.meta.outputsToInstall or [ ]; - actualOutputs = attrs.outputs or [ "out" ]; - missingOutputs = filter (output: !elem output actualOutputs) expectedOutputs; - in - '' - The package ${getNameWithVersion attrs} has set meta.outputsToInstall to: ${builtins.concatStringsSep ", " expectedOutputs} - - however ${getNameWithVersion attrs} only has the outputs: ${builtins.concatStringsSep ", " actualOutputs} - - and is missing the following outputs: - - ${concatStrings (map (output: " - ${output}\n") missingOutputs)} - ''; - metaType = let types = import ./meta-types.nix { inherit lib; }; diff --git a/pkgs/stdenv/generic/remediation.nix b/pkgs/stdenv/generic/remediation.nix new file mode 100644 index 0000000000000..9aa76cd5ebcbc --- /dev/null +++ b/pkgs/stdenv/generic/remediation.nix @@ -0,0 +1,114 @@ +{ lib }: +let + + inherit (lib) + elem + getName + concatStrings + getNameWithVersion + filter + ; + + remediation_env_var = + allow_attr: + { + Unfree = "NIXPKGS_ALLOW_UNFREE"; + UnsupportedSystem = "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM"; + NonSource = "NIXPKGS_ALLOW_NONSOURCE"; + } + .${allow_attr}; + remediation_phrase = + allow_attr: + { + Unfree = "unfree packages"; + UnsupportedSystem = "packages that are unsupported for this system"; + NonSource = "packages not built from source"; + } + .${allow_attr}; + + flakeNote = " + Note: When using `nix shell`, `nix build`, `nix develop`, etc with a flake, + then pass `--impure` in order to allow use of environment variables. + "; +in +{ + remediate_predicate = predicateConfigAttr: attrs: '' + + Alternatively you can configure a predicate to allow specific packages: + { nixpkgs.config.${predicateConfigAttr} = pkg: builtins.elem (lib.getName pkg) [ + "${getName attrs}" + ]; + } + ''; + + remediate_allowlist = allow_attr: rebuild_amendment: '' + a) To temporarily allow ${remediation_phrase allow_attr}, you can use an environment variable + for a single invocation of the nix tools. + + $ export ${remediation_env_var allow_attr}=1 + ${flakeNote} + b) For `nixos-rebuild` you can set + { nixpkgs.config.allow${allow_attr} = true; } + in configuration.nix to override this. + ${rebuild_amendment} + c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add + { allow${allow_attr} = true; } + to ~/.config/nixpkgs/config.nix. + ''; + + remediate_insecure = + attrs: + '' + + Known issues: + '' + + (concatStrings (map (issue: " - ${issue}\n") attrs.meta.knownVulnerabilities)) + + '' + + You can install it anyway by allowing this package, using the + following methods: + + a) To temporarily allow all insecure packages, you can use an environment + variable for a single invocation of the nix tools: + + $ export NIXPKGS_ALLOW_INSECURE=1 + ${flakeNote} + b) for `nixos-rebuild` you can add ‘${getNameWithVersion attrs}’ to + `nixpkgs.config.permittedInsecurePackages` in the configuration.nix, + like so: + + { + nixpkgs.config.permittedInsecurePackages = [ + "${getNameWithVersion attrs}" + ]; + } + + c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add + ‘${getNameWithVersion attrs}’ to `permittedInsecurePackages` in + ~/.config/nixpkgs/config.nix, like so: + + { + permittedInsecurePackages = [ + "${getNameWithVersion attrs}" + ]; + } + + ''; + + remediateOutputsToInstall = + attrs: + let + expectedOutputs = attrs.meta.outputsToInstall or [ ]; + actualOutputs = attrs.outputs or [ "out" ]; + missingOutputs = filter (output: !elem output actualOutputs) expectedOutputs; + in + '' + The package ${getNameWithVersion attrs} has set meta.outputsToInstall to: ${builtins.concatStringsSep ", " expectedOutputs} + + however ${getNameWithVersion attrs} only has the outputs: ${builtins.concatStringsSep ", " actualOutputs} + + and is missing the following outputs: + + ${concatStrings (map (output: " - ${output}\n") missingOutputs)} + ''; +} From f16cdd2b00ed748bb5e32e8fa9152b1dec1c5102 Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Thu, 11 Jun 2026 12:39:30 +0200 Subject: [PATCH 2/8] stdenv/meta: add support for remediation messages in problems Previously problems only gave a hint at how to define generic problem handlers. Some of our problems also have different (legacy?) ways to deal with them. While we probably want to move to a more uniform handling we should keep the escape hatches that we previously provided (config attributes, env vars) and at the same time continue provide the guidance, until it is properly deprecated. Currently there are no problems emitting remediation information and they are currently only included in the warnings. A TODO has been added to the error message as that requires further refactoring. --- pkgs/stdenv/generic/problems.nix | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkgs/stdenv/generic/problems.nix b/pkgs/stdenv/generic/problems.nix index 926075bd82298..f36a503260c73 100644 --- a/pkgs/stdenv/generic/problems.nix +++ b/pkgs/stdenv/generic/problems.nix @@ -501,7 +501,9 @@ rec { warnings = map (x: { reason = "problem"; msg = "has the following problem: ${fullMessage x}"; - remediation = "See https://nixos.org/manual/nixpkgs/unstable#sec-problems"; # TODO: Add remediation, maybe just link to docs to keep it small + remediation = + (if x ? remediation then x.remediation + "\n" else "") + + "See https://nixos.org/manual/nixpkgs/unstable#sec-problems"; }) warnProblems; error = @@ -519,6 +521,10 @@ rec { ${concatMapStringsSep "\n" (x: "- ${fullMessage x}") errorProblems} ''; ## TODO: Add mention of problem.matchers, or maybe better link to docs of that + ## TODO: Add support for a `remediation` attribute in each + ## of the errors. The output should be logically grouped + ## and the additional remediation information should be + ## local to the error message. remediation = '' See also https://nixos.org/manual/nixpkgs/unstable#sec-problems To allow evaluation regardless, use: From c3cbf29540385ab3198abad6b2351bdf7dd3ef45 Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Mon, 8 Jun 2026 11:32:18 +0200 Subject: [PATCH 3/8] meta/problems: add hostPlatform to genCheckProblems This will enable future work where e.g. unsupported platform errors can be handled with the new problems framework. --- pkgs/stdenv/generic/check-meta.nix | 2 +- pkgs/stdenv/generic/problems.nix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index 25ecf31372f3b..b540c8b351c08 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -622,7 +622,7 @@ let { meta, attrs }: let invalid = checkValidity' attrs; - problems = checkProblems attrs; + problems = checkProblems hostPlatform attrs; in if isNull invalid then if isNull problems then diff --git a/pkgs/stdenv/generic/problems.nix b/pkgs/stdenv/generic/problems.nix index f36a503260c73..8f33ee54f23e7 100644 --- a/pkgs/stdenv/generic/problems.nix +++ b/pkgs/stdenv/generic/problems.nix @@ -444,6 +444,7 @@ rec { problem: problem // { condition = problem.condition config; } ) automaticProblems; in + hostPlatform: attrs: let pname = getName attrs; From 6d610c0a6d33a981fd75f824665f7e036ad8b3fa Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Mon, 8 Jun 2026 14:07:08 +0200 Subject: [PATCH 4/8] meta/problems: pass hostPlatform into automaticProblems This allows the problems to depend on the current hostPlatform rather than just on the attributes passed to the functions. In a future change we can then use the hostSystem to implement the unsupportedSystem which will then become a meta.problem rather than an unconditional eval error. --- pkgs/stdenv/generic/problems.nix | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgs/stdenv/generic/problems.nix b/pkgs/stdenv/generic/problems.nix index 8f33ee54f23e7..72096f7da7f04 100644 --- a/pkgs/stdenv/generic/problems.nix +++ b/pkgs/stdenv/generic/problems.nix @@ -102,7 +102,7 @@ rec { # If `description` is not defined, the derivation is probably not a package. # Simply checking whether `meta` is defined is insufficient, # as some fetchers and trivial builders do define meta. - config: attrs: + config: attrs: _: # Order of checks optimised for short-circuiting the common case of having maintainers (attrs.meta.maintainers or [ ] == [ ]) && (attrs.meta.teams or [ ] == [ ]) @@ -126,16 +126,16 @@ rec { else x: false; in - attrs: attrs.meta.broken or false && !allowBroken && !allowBrokenPredicate attrs; + attrs: _: attrs.meta.broken or false && !allowBroken && !allowBrokenPredicate attrs; value.message = "This package is broken."; } ]; genAutomaticProblems = - config: attrs: + config: attrs: hostPlatform: listToAttrs ( map (problem: lib.nameValuePair problem.kindName problem.value) ( - filter (problem: problem.condition config attrs) automaticProblems + filter (problem: problem.condition config attrs hostPlatform) automaticProblems ) ); @@ -444,8 +444,7 @@ rec { problem: problem // { condition = problem.condition config; } ) automaticProblems; in - hostPlatform: - attrs: + hostPlatform: attrs: let pname = getName attrs; manualProblems = attrs.meta.problems or { }; @@ -455,7 +454,8 @@ rec { # No automatic problems that needs handling all ( problem: - problem.condition attrs -> handlerForProblem pname problem.kindName problem.kindName == "ignore" + problem.condition attrs hostPlatform + -> handlerForProblem pname problem.kindName problem.kindName == "ignore" ) automaticProblemsConfigCache && ( # No manual problems @@ -470,7 +470,7 @@ rec { else # Slow path, only here we actually figure out which problems we need to handle let - problems = attrs.meta.problems or { } // genAutomaticProblems config attrs; + problems = attrs.meta.problems or { } // genAutomaticProblems config attrs hostPlatform; problemsToHandle = filter (v: v.handler != "ignore") ( mapAttrsToList (name: problem: rec { inherit name; From 1fce71b8f615079ed43ef8572294e0eff2c69940 Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Mon, 8 Jun 2026 16:45:34 +0200 Subject: [PATCH 5/8] stdenv/meta/problems: make automaticProblems an attrset The idea here being that we don't have to return a `kindName` anymore since we can only ever have one implementation of a kind anyway. The previous implementation would silently shadow previous problems of the same kind. Notes: * a builtins.filterMapAttrs would be nice to remove a few extra copies but the new code doesn't seem to be slower. There is a PR on Nix to introduce filterAttrs which is close and could maybe steered the right way as filterMap vs filter is just the map+filter function arg: https://github.com/NixOS/nix/pull/15100/files --- pkgs/stdenv/generic/problems.nix | 104 ++++++++++++++++--------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/pkgs/stdenv/generic/problems.nix b/pkgs/stdenv/generic/problems.nix index 72096f7da7f04..c3dc256dd7dd9 100644 --- a/pkgs/stdenv/generic/problems.nix +++ b/pkgs/stdenv/generic/problems.nix @@ -73,7 +73,7 @@ rec { # TODO: Combine this and automaticProblems into a `{ removal = { manual = true; ... }; ... }` structure for less error-prone changes kinds = rec { # Automatic and manual problem kinds - known = map (problem: problem.kindName) automaticProblems ++ manual; + known = (builtins.attrNames automaticProblems) ++ manual; # Problem kinds that are currently allowed to be specified in `meta.problems` manual = [ "removal" @@ -90,53 +90,57 @@ rec { unique' = genAttrs unique (k: null); }; - automaticProblems = [ - { - kindName = "maintainerless"; - condition = - # To get usable output, we want to avoid flagging "internal" derivations. - # Because we do not have a way to reliably decide between internal or - # external derivation, some heuristics are required to decide. - # - # If `outputHash` is defined, the derivation is a FOD, such as the output of a fetcher. - # If `description` is not defined, the derivation is probably not a package. - # Simply checking whether `meta` is defined is insufficient, - # as some fetchers and trivial builders do define meta. - config: attrs: _: + automaticProblems = { + maintainerless = ( + config: attrs: _: + # To get usable output, we want to avoid flagging "internal" derivations. + # Because we do not have a way to reliably decide between internal or + # external derivation, some heuristics are required to decide. + # + # If `outputHash` is defined, the derivation is a FOD, such as the output of a fetcher. + # If `description` is not defined, the derivation is probably not a package. + # Simply checking whether `meta` is defined is insufficient, + # as some fetchers and trivial builders do define meta. + if # Order of checks optimised for short-circuiting the common case of having maintainers (attrs.meta.maintainers or [ ] == [ ]) && (attrs.meta.teams or [ ] == [ ]) && (!attrs ? outputHash) - && (attrs ? meta.description); - value.message = "This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute."; - } - { - kindName = "broken"; - condition = - config: - let - # TODO: Consider deprecating this or making it generic for all problems - allowBroken = config.allowBroken || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1"; - - allowBrokenPredicate = - if config ? allowBrokenPredicate then - lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2605) - "config.allowBrokenPredicate is deprecated, use config.problems.handlers.myPackage.broken = \"warn\" for individual packages instead." - config.allowBrokenPredicate - else - x: false; - in - attrs: _: attrs.meta.broken or false && !allowBroken && !allowBrokenPredicate attrs; - value.message = "This package is broken."; - } - ]; + && (attrs ? meta.description) + then + { + message = "This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute."; + } + else + false + ); + broken = ( + config: + let + # TODO: Consider deprecating this or making it generic for all problems + allowBroken = config.allowBroken || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1"; + allowBrokenPredicate = + if config ? allowBrokenPredicate then + lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2605) + "config.allowBrokenPredicate is deprecated, use config.problems.handlers.myPackage.broken = \"warn\" for individual packages instead." + config.allowBrokenPredicate + else + x: false; + in + attrs: _: + if (attrs.meta.broken or false && !allowBroken && !allowBrokenPredicate attrs) then + { + message = "This package is broken."; + } + else + false + ); + }; genAutomaticProblems = config: attrs: hostPlatform: - listToAttrs ( - map (problem: lib.nameValuePair problem.kindName problem.value) ( - filter (problem: problem.condition config attrs hostPlatform) automaticProblems - ) + filterAttrs (_: v: v != false) ( + mapAttrs (kindName: problemFn: problemFn config attrs hostPlatform) automaticProblems ); # A module system type for Nixpkgs config @@ -440,9 +444,7 @@ rec { handlerForProblem ; # Makes sure that automatic problems can cache with just config applied - automaticProblemsConfigCache = map ( - problem: problem // { condition = problem.condition config; } - ) automaticProblems; + automaticProblemsConfigCache = mapAttrs (_: problem: problem config) automaticProblems; in hostPlatform: attrs: let @@ -452,11 +454,15 @@ rec { if # Fast path for when there's no problem that needs to be handled # No automatic problems that needs handling - all ( - problem: - problem.condition attrs hostPlatform - -> handlerForProblem pname problem.kindName problem.kindName == "ignore" - ) automaticProblemsConfigCache + all (v: v) ( + mapAttrsToList ( + kindName: problemFn: + let + v = problemFn attrs hostPlatform; + in + v != false -> handlerForProblem pname kindName kindName == "ignore" + ) automaticProblemsConfigCache + ) && ( # No manual problems manualProblems == { } From 9d01bd0db0f3a9743626f03be342c09c1cce0e79 Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Mon, 8 Jun 2026 15:13:41 +0200 Subject: [PATCH 6/8] stdenv/meta/problems: add unsupported platform support This moves the unsupported platform support into the meta.problems code while retaining all the typical (legacy?) escape hatches. Benefit of this work is that the generic problem handlers can be used to deal with the errors instead of just blanket opt-outs. An example use case of putting this on warn instead of error would be when porting to a new platform. You might want to attempt compiling all packages but at the same time want to know which ones are actually supposedly unsupported (so you can later on fix their platform(s) attribute). --- pkgs/stdenv/generic/check-meta.nix | 6 +- pkgs/stdenv/generic/problems.nix | 58 ++++++++++++++++++- .../problems/cases/unsupported/default.nix | 14 +++++ .../cases/unsupported/expected-stderr | 41 +++++++++++++ pkgs/top-level/config.nix | 5 ++ 5 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 pkgs/test/problems/cases/unsupported/default.nix create mode 100644 pkgs/test/problems/cases/unsupported/expected-stderr diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index b540c8b351c08..9fbbc9ec17be0 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -44,14 +44,15 @@ let getEnv ; - inherit (import ./remediation.nix { inherit lib; }) + remediationLib = import ./remediation.nix { inherit lib; }; + inherit (remediationLib) remediateOutputsToInstall remediate_insecure remediate_allowlist remediate_predicate ; - inherit (import ./problems.nix { inherit lib; }) + inherit (import ./problems.nix { inherit lib remediationLib; }) problemsType genCheckProblems ; @@ -379,6 +380,7 @@ let package.meta.platforms = ${toPretty' (attrs.meta.platforms or [ ])} package.meta.badPlatforms = ${toPretty' (attrs.meta.badPlatforms or [ ])} ''; + remediation = remediate_allowlist "UnsupportedSystem" ""; } else if hasDisallowedInsecure attrs then diff --git a/pkgs/stdenv/generic/problems.nix b/pkgs/stdenv/generic/problems.nix index c3dc256dd7dd9..56917aeccc7a8 100644 --- a/pkgs/stdenv/generic/problems.nix +++ b/pkgs/stdenv/generic/problems.nix @@ -11,7 +11,10 @@ nix-build -A tests.problems */ -{ lib }: +{ + lib, + remediationLib ? (import ./remediation.nix { inherit lib; }), +}: rec { @@ -19,6 +22,14 @@ rec { escapeNixIdentifier ; + inherit (lib.meta) + platformMatch + ; + + inherit (builtins) + getEnv + ; + inherit (lib) any listToAttrs @@ -50,6 +61,10 @@ rec { genAttrs ; + inherit (lib.generators) + toPretty + ; + handlers = rec { # Ordered from less to more levels = [ @@ -135,6 +150,47 @@ rec { else false ); + unsupported = ( + config: attrs: hostPlatform: + let + isHostPlatformInList = + default: list: + if list == null then + default + else + (elem hostPlatform.system list) || any (platformMatch hostPlatform) list; + + inPlatforms = isHostPlatformInList true (attrs.meta.platforms or null); + inBadPlatforms = isHostPlatformInList false (attrs.meta.badPlatforms or null); + allowUnsupportedSystem = + config.allowUnsupportedSystem || getEnv "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM" == "1"; + in + if (!inPlatforms || inBadPlatforms) && !allowUnsupportedSystem then + { + message = + let + toPretty' = toPretty { + allowPrettyValues = true; + indent = " "; + }; + in + # FIXME: Remediation is inlined into the message so it is + # local within the error output, this should be properly + # structured (as in as remediation attribute) and then the + # `processProblems` function should "print" it properly group + # it together with the respective error(s). + '' + This package is not available on the requested hostPlatform: + hostPlatform.system = "${hostPlatform.system}" + package.meta.platforms = ${toPretty' (attrs.meta.platforms or [ ])} + package.meta.badPlatforms = ${toPretty' (attrs.meta.badPlatforms or [ ])} + + ${remediationLib.remediate_allowlist "UnsupportedSystem" ""} + ''; + } + else + false + ); }; genAutomaticProblems = diff --git a/pkgs/test/problems/cases/unsupported/default.nix b/pkgs/test/problems/cases/unsupported/default.nix new file mode 100644 index 0000000000000..40c62417fff88 --- /dev/null +++ b/pkgs/test/problems/cases/unsupported/default.nix @@ -0,0 +1,14 @@ +{ nixpkgs }: +let + pkgs = import nixpkgs { + system = "x86_64-linux"; + overlays = [ ]; + config = { }; + }; +in +pkgs.stdenvNoCC.mkDerivation { + pname = "a"; + version = "0"; + meta.platforms = [ "aarch64-darwin" ]; + meta.badPlatforms = [ "x86_64-linux" ]; +} diff --git a/pkgs/test/problems/cases/unsupported/expected-stderr b/pkgs/test/problems/cases/unsupported/expected-stderr new file mode 100644 index 0000000000000..68ad4d1d67ed9 --- /dev/null +++ b/pkgs/test/problems/cases/unsupported/expected-stderr @@ -0,0 +1,41 @@ +(stack trace truncated; use '--show-trace' to show the full, detailed trace) + +error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:11 because it has problems: +- unsupported: This package is not available on the requested hostPlatform: + hostPlatform.system = "x86_64-linux" + package.meta.platforms = [ + "aarch64-darwin" + ] + package.meta.badPlatforms = [ + "x86_64-linux" + ] + +a) To temporarily allow packages that are unsupported for this system, you can use an environment variable + for a single invocation of the nix tools. + + $ export NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM=1 + + Note: When using `nix shell`, `nix build`, `nix develop`, etc with a flake, + then pass `--impure` in order to allow use of environment variables. + +b) For `nixos-rebuild` you can set + { nixpkgs.config.allowUnsupportedSystem = true; } +in configuration.nix to override this. + +c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add + { allowUnsupportedSystem = true; } +to ~/.config/nixpkgs/config.nix. + + + +See also https://nixos.org/manual/nixpkgs/unstable#sec-problems +To allow evaluation regardless, use: +- Nixpkgs import: import nixpkgs { config = ; } +- NixOS: nixpkgs.config = ; +- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix + + { + problems.handlers = { + a.unsupported = "warn"; # or "ignore" + }; + } diff --git a/pkgs/top-level/config.nix b/pkgs/top-level/config.nix index 526dd41827026..cd204c06c3d44 100644 --- a/pkgs/top-level/config.nix +++ b/pkgs/top-level/config.nix @@ -526,6 +526,11 @@ in kind = "maintainerless"; handler = "warn"; }) + + { + kind = "unsupported"; + handler = "error"; + } ]; }; From 8e976d8bf514c10abbd1baf514668b9c6179b0c1 Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Wed, 10 Jun 2026 11:00:05 +0200 Subject: [PATCH 7/8] HACK: deactivate the traditional unsupported code for testing --- pkgs/stdenv/generic/check-meta.nix | 38 ------------------------------ 1 file changed, 38 deletions(-) diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index 9fbbc9ec17be0..68a821a23668b 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -103,9 +103,6 @@ let hasBlocklistedLicense = hasListedLicense blocklist; - allowUnsupportedSystem = - config.allowUnsupportedSystem || getEnv "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM" == "1"; - isUnfree = licenses: if isAttrs licenses && licenses ? "licenseType" then @@ -125,20 +122,6 @@ let isMarkedBroken = attrs: attrs.meta.broken or false; - # Logical inversion of meta.availableOn for hostPlatform - hasUnsupportedPlatform = - hostPlatform: - let - inherit (hostPlatform) system; - # in almost all cases, meta.platforms is a simple list of strings, and we - # can just check if it contains the current system. we only run the more - # intensive platformMatch if necessary - anyHostPlatform = list: elem system list || any (platformMatch hostPlatform) list; - in - pkg: - pkg ? meta.platforms && !(anyHostPlatform pkg.meta.platforms) - || pkg ? meta.badPlatforms && anyHostPlatform pkg.meta.badPlatforms; - isMarkedInsecure = attrs: (attrs.meta.knownVulnerabilities or [ ]) != [ ]; # Allow granular checks to allow only some unfree packages @@ -320,9 +303,6 @@ let # Along with a boolean flag for each reason checkValidity = hostPlatform: - let - hasUnsupportedPlatform' = hasUnsupportedPlatform hostPlatform; - in attrs: if !attrs ? meta then null @@ -365,24 +345,6 @@ let msg = "contains elements not built from source (‘${showSourceType attrs.meta.sourceProvenance}’)"; remediation = remediate_allowlist "NonSource" (remediate_predicate "allowNonSourcePredicate" attrs); } - else if hasUnsupportedPlatform' attrs && !allowUnsupportedSystem then - let - toPretty' = toPretty { - allowPrettyValues = true; - indent = " "; - }; - in - { - reason = "unsupported"; - msg = '' - is not available on the requested hostPlatform: - hostPlatform.system = "${hostPlatform.system}" - package.meta.platforms = ${toPretty' (attrs.meta.platforms or [ ])} - package.meta.badPlatforms = ${toPretty' (attrs.meta.badPlatforms or [ ])} - ''; - - remediation = remediate_allowlist "UnsupportedSystem" ""; - } else if hasDisallowedInsecure attrs then { reason = "insecure"; From fa4b43ec3d5be16fc6dc2c37338e0346d43084cb Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Thu, 11 Jun 2026 13:19:47 +0200 Subject: [PATCH 8/8] fixup! HACK: deactivate the traditional unsupported code for testing --- pkgs/stdenv/generic/check-meta.nix | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index 68a821a23668b..691ed7a9a6268 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -392,9 +392,6 @@ let # validity = checkMeta.assertValidity hostPlatform { inherit meta attrs; }; commonMeta = hostPlatform: - let - hasUnsupportedPlatform' = hasUnsupportedPlatform hostPlatform; - in { validity, attrs, @@ -533,7 +530,7 @@ let # Expose the result of the checks for everyone to see. unfree = hasUnfreeLicense attrs; broken = isMarkedBroken attrs; - unsupported = hasUnsupportedPlatform' attrs; + unsupported = warn "Usage of deprectaed `unsupported` marker? FIXME: this should be gathered from the problems emitted for this specific derivation" false; insecure = isMarkedInsecure attrs; available =