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 <raito@lix.systems>
This commit is contained in:
Raito Bezarius
2025-08-25 09:51:07 +00:00
parent 8d55251ebd
commit d6ccc6b89c
2 changed files with 29 additions and 25 deletions
+27 -25
View File
@@ -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<Result<Goal::WorkResult>> DerivationGoal::buildDone(std::shared_ptr<Error> 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
+2
View File
@@ -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