From af34b1ca592fe0213503ff67ba12dd6f89790aa6 Mon Sep 17 00:00:00 2001 From: Pyra <92104930+pyranota@users.noreply.github.com> Date: Mon, 29 Sep 2025 14:12:06 +0200 Subject: [PATCH] fix(uv): log stdout on `uv pip install` error (#6702) Signed-off-by: pyranota --- .../windmill-worker/src/python_executor.rs | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/backend/windmill-worker/src/python_executor.rs b/backend/windmill-worker/src/python_executor.rs index 5b742feb4b..8021672fe8 100644 --- a/backend/windmill-worker/src/python_executor.rs +++ b/backend/windmill-worker/src/python_executor.rs @@ -1927,12 +1927,21 @@ pub async fn handle_python_reqs( } }; - let mut stderr_buf = String::new(); - let mut stderr_pipe = uv_install_proccess - .stderr() - .take() - .ok_or(anyhow!("Cannot take stderr from uv_install_proccess"))?; - let stderr_future = stderr_pipe.read_to_string(&mut stderr_buf); + let (mut stderr_buf, mut stdout_buf) = Default::default(); + let (mut stderr_pipe, mut stdout_pipe) = ( + uv_install_proccess + .stderr() + .take() + .ok_or(anyhow!("Cannot take stderr from uv_install_proccess"))?, + uv_install_proccess + .stdout() + .take() + .ok_or(anyhow!("Cannot take stdout from uv_install_proccess"))? + ); + let (stderr_future, stdout_future) = ( + stderr_pipe.read_to_string(&mut stderr_buf), + stdout_pipe.read_to_string(&mut stdout_buf) + ); if let Some(pid) = pids.lock().await.get_mut(i) { *pid = uv_install_proccess.id(); @@ -1950,10 +1959,10 @@ pub async fn handle_python_reqs( pids.lock().await.get_mut(i).and_then(|e| e.take()); return Err(anyhow::anyhow!("uv pip install was canceled")); }, - (_, exitstatus) = async { + (_, _, exitstatus) = async { // See tokio::process::Child::wait_with_output() for more context // Sometimes uv_install_proccess.wait() is not exiting if stderr is not awaited before it :/ - (stderr_future.await, Box::into_pin(uv_install_proccess.wait()).await) + (stderr_future.await, stdout_future.await, Box::into_pin(uv_install_proccess.wait()).await) } => match exitstatus { Ok(status) => if !status.success() { tracing::warn!( @@ -1967,7 +1976,7 @@ pub async fn handle_python_reqs( &job_id, w_id, format!( - "\nError while installing {}:\n{stderr_buf}", + "\nError while installing {}: \nStderr:\n{stderr_buf}\nStdout:\n{stdout_buf}", &req ), &conn,