libstore/build: report better error messages for --check

When --check is ran with no output, this is seen as having *SOME*
invalid outputs, actually, ALL of them are invalid here.

Instead of reporting a confusing error, let's consider ALL of outputs
being invalid to be no output at all available and advise the user to
rerun the build without --check.

If there's *some* (>0) invalid outputs, let's print them exactly to give
a chance to the user to remediate this.

Fixes #485.

Change-Id: I00955ef9ea4f129e2c98d68c73b1e981f90278a0
Signed-off-by: Raito Bezarius <raito@lix.systems>
This commit is contained in:
Raito Bezarius
2026-01-10 12:42:50 +01:00
parent 8f9ed687da
commit e9cccd47e2
3 changed files with 53 additions and 5 deletions
@@ -0,0 +1,33 @@
---
synopsis: "`--check` or `--rebuild` is clearer about a missing path"
cls: []
issues: [fj#485]
category: "Improvements"
credits: [raito]
---
Previously, when running Lix with --check or --rebuild, failures often surfaced
as an unhelpful error:
> "some outputs of '...' are not valid, so checking is not possible"
This message could mean two different things:
- The requested output paths don't exist at all, or,
- Some outputs exist but are not known to Lix
Lix cannot reliably distinguish these cases, so it treated them the same.
We've updated the error messages to clarify what Lix can determine: whether any
valid outputs (> 0) are present or whether no outputs are available.
When no valid outputs can be found, Lix will now suggest building the derivation
normally (without --check or --rebuild) before trying again.
When some valid outputs are present, Lix now reports which ones are valid,
shows the full list of known outputs, and also suggests building the derivation
normally.
In the future, Lix may automate this recovery step when it knows how to rebuild
the paths, but implementing that safely requires more extensive changes to the
codebase.
+19 -3
View File
@@ -353,9 +353,25 @@ try {
if (buildMode == bmRepair && allValid) {
co_return TRY_AWAIT(repairClosure());
}
if (buildMode == bmCheck && !allValid)
throw Error("some outputs of '%s' are not valid, so checking is not possible",
worker.store.printStorePath(drvPath));
if (buildMode == bmCheck && validOutputs.empty()) {
throw Error(
"'%s' has no valid outputs registered in the store, build it first and re-run the "
"check command after that",
worker.store.printStorePath(drvPath)
);
} else if (buildMode == bmCheck && !allValid) {
auto wantedOutputsStr = wantedOutputs.to_string();
auto validOutputsNames = concatStringsSep(", ", std::views::keys(validOutputs));
throw Error(
"Not all outputs of '%s' are registered and valid in this store ('%s' are available, "
"'%s' are missing). "
"Rebuild the derivation normally and re-run the check command after that",
worker.store.printStorePath(drvPath),
validOutputsNames == "" ? "none" : validOutputsNames,
wantedOutputsStr == "*" ? "all" : wantedOutputsStr
);
}
/* Nothing to wait for; tail call */
co_return TRY_AWAIT(gaveUpOnSubstitution());
+1 -2
View File
@@ -46,8 +46,7 @@ def test_good(nix: Nix):
@with_files(get_global_asset_pack("fixed"))
def test_check(nix: Nix):
res = nix.nix_build(["fixed.nix", "-A", "check", "--check"]).run().expect(1)
assert "some outputs of " in res.stderr_plain
assert "are not valid, so checking is not possible" in res.stderr_plain
assert "has no valid outputs registered in the store" in res.stderr_plain
@with_files(get_global_asset_pack("fixed"))