From d6ccc6b89c35873c0fd4744d54f583c287c440b2 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 2 Aug 2025 18:34:23 +0200 Subject: [PATCH] libstore/build: make build errors extensible by children Currently, DerivationGoal prints a pretty generic message. For many valid reasons, children may have better knowledge of the detail of what has happened and would like to extend the error message. What we did is to printError at convenient places but this is counterproductive because the build error can bury the notes. This is still not perfect because there's no fine-grained structured information that children can use to act upon the generic messaging, but this is already an improvement for LocalDerivationGoal and keep failed which will occur in the next change. Change-Id: I5835cbbb30c4f2aa64abefb83999018d30ca4a0c Signed-off-by: Raito Bezarius --- lix/libstore/build/derivation-goal.cc | 52 ++++++++++++++------------- lix/libstore/build/derivation-goal.hh | 2 ++ 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/lix/libstore/build/derivation-goal.cc b/lix/libstore/build/derivation-goal.cc index bcfb88f14..b402650f4 100644 --- a/lix/libstore/build/derivation-goal.cc +++ b/lix/libstore/build/derivation-goal.cc @@ -907,6 +907,32 @@ void runPostBuildHook( proc.getStdout()->drainInto(sink); } +std::string DerivationGoal::buildErrorContents(const std::string & exitMsg, bool diskFull) +{ + auto msg = fmt("builder for '%s' %s", Magenta(worker.store.printStorePath(drvPath)), exitMsg); + + if (!logger->isVerbose() && !logTail.empty()) { + msg += fmt(";\nlast %d log lines:\n", logTail.size()); + for (auto & line : logTail) { + msg += "> "; + msg += line; + msg += "\n"; + } + auto nixLogCommand = + experimentalFeatureSettings.isEnabled(Xp::NixCommand) ? "nix log" : "nix-store -l"; + msg += + fmt("For full logs, run: '" ANSI_BOLD "%s %s" ANSI_NORMAL "'.", + nixLogCommand, + worker.store.printStorePath(drvPath)); + } + + if (diskFull) { + msg += "\nnote: build failure may have been caused by lack of free disk space"; + } + + return msg; +} + kj::Promise> DerivationGoal::buildDone(std::shared_ptr remoteError ) noexcept try { @@ -961,36 +987,12 @@ try { } bool diskFull = false; - try { /* Check the exit status. */ if (!exited || exitCode != 0) { - diskFull |= cleanupDecideWhetherDiskFull(); - - auto msg = - fmt("builder for '%s' %s", Magenta(worker.store.printStorePath(drvPath)), exitMsg); - - if (!logger->isVerbose() && !logTail.empty()) { - msg += fmt(";\nlast %d log lines:\n", logTail.size()); - for (auto & line : logTail) { - msg += "> "; - msg += line; - msg += "\n"; - } - auto nixLogCommand = experimentalFeatureSettings.isEnabled(Xp::NixCommand) - ? "nix log" - : "nix-store -l"; - msg += fmt("For full logs, run '" ANSI_BOLD "%s %s" ANSI_NORMAL "'.", - nixLogCommand, - worker.store.printStorePath(drvPath)); - } - - if (diskFull) - msg += "\nnote: build failure may have been caused by lack of free disk space"; - - throw BuildError("%s", msg); + throw BuildError(buildErrorContents(exitMsg, diskFull)); } /* Compute the FS closure of the outputs and register them as diff --git a/lix/libstore/build/derivation-goal.hh b/lix/libstore/build/derivation-goal.hh index c78a1d1a7..dba8c0ce7 100644 --- a/lix/libstore/build/derivation-goal.hh +++ b/lix/libstore/build/derivation-goal.hh @@ -327,6 +327,8 @@ protected: WorkResult tooMuchLogs(); void flushLine(); + virtual std::string buildErrorContents(const std::string & exitMsg, bool diskFull); + public: /** * Wrappers around the corresponding Store method that first consults the