Skip to content

Commit 863e73a

Browse files
authored
Skip Windows Python interpreters that return a broken MSIX package code (#14636)
Currently we treat all spawn failures as fatal, because they indicate a broken interpreter. In this case, I think we should just skip these broken interpreters — though I don't know the root cause of why it's broken yet. Closes #14637 See https://discord.com/channels/1039017663004942429/1039017663512449056/1394758502647333025
1 parent ab2bd01 commit 863e73a

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

crates/uv-python/src/discovery.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,14 @@ impl Error {
884884
);
885885
false
886886
}
887+
#[cfg(windows)]
888+
InterpreterError::CorruptWindowsPackage { path, err } => {
889+
debug!(
890+
"Skipping bad interpreter at {} from {source}: {err}",
891+
path.display()
892+
);
893+
false
894+
}
887895
InterpreterError::NotFound(path)
888896
| InterpreterError::BrokenSymlink(BrokenSymlink { path, .. }) => {
889897
// If the interpreter is from an active, valid virtual environment, we should

crates/uv-python/src/interpreter.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ use crate::{
3434
VirtualEnvironment,
3535
};
3636

37+
#[cfg(windows)]
38+
use windows_sys::Win32::Foundation::{APPMODEL_ERROR_NO_PACKAGE, ERROR_CANT_ACCESS_FILE};
39+
3740
/// A Python executable and its associated platform markers.
3841
#[derive(Debug, Clone)]
3942
pub struct Interpreter {
@@ -760,6 +763,13 @@ pub enum Error {
760763
#[source]
761764
err: io::Error,
762765
},
766+
#[cfg(windows)]
767+
#[error("Failed to query Python interpreter at `{path}`")]
768+
CorruptWindowsPackage {
769+
path: PathBuf,
770+
#[source]
771+
err: io::Error,
772+
},
763773
#[error("{0}")]
764774
UnexpectedResponse(UnexpectedResponseError),
765775
#[error("{0}")]
@@ -872,10 +882,23 @@ impl InterpreterInfo {
872882
.arg("-c")
873883
.arg(script)
874884
.output()
875-
.map_err(|err| Error::SpawnFailed {
876-
path: interpreter.to_path_buf(),
877-
err,
878-
})?;
885+
.map_err(
886+
|err| match err.raw_os_error().and_then(|code| u32::try_from(code).ok()) {
887+
// These error codes are returned if the Python interpreter is a corrupt MSIX
888+
// package, which we want to differentiate from a typical spawn failure.
889+
#[cfg(windows)]
890+
Some(APPMODEL_ERROR_NO_PACKAGE | ERROR_CANT_ACCESS_FILE) => {
891+
Error::CorruptWindowsPackage {
892+
path: interpreter.to_path_buf(),
893+
err,
894+
}
895+
}
896+
_ => Error::SpawnFailed {
897+
path: interpreter.to_path_buf(),
898+
err,
899+
},
900+
},
901+
)?;
879902

880903
if !output.status.success() {
881904
let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string();

0 commit comments

Comments
 (0)