From 1000849865424892c50500eeba86c8431fcee9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 11 Jun 2026 14:03:56 +0000 Subject: [PATCH] queue-runner: do not fail uploads when the build log is missing upload_to_store opened the local build log and treated any error as fatal for the whole message, so paths without a log were never copied to the binary cache and their builds failed. Logs are legitimately absent for steps that did not run on this instance: substituted paths or builds finished before a queue runner restart. Observed on a 120-build nixos-small evaluation: 53 'Failed to upload ... uploader state I/O' errors in 10 minutes and 65 builds failing with status 2, with the corresponding build-logs directories empty. Skip the log upload with a warning when the file does not exist. Other I/O errors still fail the upload. --- .../hydra-queue-runner/src/state/uploader.rs | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/subprojects/hydra-queue-runner/src/state/uploader.rs b/subprojects/hydra-queue-runner/src/state/uploader.rs index ad6413acf..4893bb22f 100644 --- a/subprojects/hydra-queue-runner/src/state/uploader.rs +++ b/subprojects/hydra-queue-runner/src/state/uploader.rs @@ -156,21 +156,38 @@ impl Uploader { msg: &Message, closure: &[harmonia_store_path_info::ValidPathInfo], ) -> Result<(), UploaderError> { - // Upload log file - (|| async { - let file = fs_err::tokio::File::open(msg.log_local_path.as_path()).await?; - let reader = Box::new(tokio::io::BufReader::new(file)); - remote_store - .upsert_file_stream(&msg.log_remote_path, reader, "text/plain; charset=utf-8") + // Steps that did not run here (substituted paths, builds finished + // before a restart) have no log file. A missing log must not block + // the NAR upload. + match fs_err::tokio::metadata(msg.log_local_path.as_path()).await { + Ok(_) => { + (|| async { + let file = fs_err::tokio::File::open(msg.log_local_path.as_path()).await?; + let reader = Box::new(tokio::io::BufReader::new(file)); + remote_store + .upsert_file_stream( + &msg.log_remote_path, + reader, + "text/plain; charset=utf-8", + ) + .await?; + Ok::<(), UploaderError>(()) + }) + .retry( + ExponentialBuilder::default() + .with_max_delay(std::time::Duration::from_secs(30)) + .with_max_times(3), + ) .await?; - Ok::<(), UploaderError>(()) - }) - .retry( - ExponentialBuilder::default() - .with_max_delay(std::time::Duration::from_secs(30)) - .with_max_times(3), - ) - .await?; + } + Err(e) if e.kind() == std::io::ErrorKind::NotFound => { + tracing::warn!( + "no build log at {}, skipping log upload", + msg.log_local_path.display() + ); + } + Err(e) => return Err(e.into()), + } // Copy NARs let missing_paths: hashbrown::HashSet = remote_store