BigPizzaV3/CodexPlusPlus · error · anyhow::Error
启动安装包失败:{error}
Error message
启动安装包失败:{error} What it means
On Windows, launch_installer spawns the downloaded installer with std::process::Command::new(path) (using CREATE_NO_WINDOW). If the OS refuses to spawn — file missing, not an executable, permission denied, AV interference — the io::Error is wrapped as "启动安装包失败:{error}". This is spawn failure (the process never started), not a non-zero installer exit code, which launch_installer does not check at all.
Source
Thrown at crates/codex-plus-core/src/update.rs:418
|| name.ends_with("setup.exe")
|| name.ends_with("installer.exe"))
}
fn is_macos_installer_asset(name: &str) -> bool {
// Loose shape check; arch preference is handled by platform_asset_rank
// via is_macos_native_arch_asset.
name.contains("codex") && name.contains("plus") && name.ends_with(".dmg")
}
pub fn launch_installer(path: &Path) -> anyhow::Result<()> {
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
std::process::Command::new(path)
.creation_flags(crate::windows_integration::CREATE_NO_WINDOW)
.spawn()
.map(|_| ())
.map_err(|error| anyhow::anyhow!("启动安装包失败:{error}"))
}
#[cfg(target_os = "macos")]
{
std::process::Command::new("open")
.arg(path)
.spawn()
.map(|_| ())
.map_err(|error| anyhow::anyhow!("打开 DMG 失败:{error}"))
}
#[cfg(all(not(windows), not(target_os = "macos")))]
{
let _ = path;
anyhow::bail!("当前平台不支持启动安装包")
}
}
View on GitHub (pinned to 1f431ae49b)
Solutions
- Verify the path exists and has the expected .exe extension immediately before launching
- Re-run perform_update to re-download, then launch without delay
- Check antivirus/quarantine history; add an exclusion or code-sign the installer
- Keep the download directory alive until the installer has been spawned
Example fix
// before
launch_installer(&install.installer_path)?;
// after
let path = &install.installer_path;
if !path.is_file() {
anyhow::bail!("installer missing before launch: {}", path.display());
}
launch_installer(path)?; Defensive patterns
Strategy: try-catch
Validate before calling
let path = &install.installer_path;
if !path.is_file() || path.extension().is_none_or(|e| e != "exe") {
anyhow::bail!("installer missing or not an exe before launch: {}", path.display());
}
launch_installer(path)?; Try / catch
match launch_installer(&install.installer_path) {
Ok(()) => { /* spawned */ }
Err(err) if err.to_string().contains("启动安装包失败") => {
// re-download via perform_update and retry the launch once; check AV quarantine if it persists
}
Err(err) => return Err(err),
} Prevention
- Keep the download directory alive until the installer has actually spawned
- Code-sign installers and document AV exclusions to avoid quarantine of the downloaded binary
- Verify existence and extension right before spawning
When it happens
Trigger: The installer file was deleted between perform_update finishing and launch_installer being called (temp-dir cleanup); the downloaded asset was not actually a .exe (wrong platform asset selected); antivirus/SmartScreen quarantined the binary; the path is on a blocked or UNC location.
Common situations: Apps downloading to a temp dir the OS cleans aggressively; managed devices where AV auto-quarantines unsigned installers; races with cleanup code running right after the update completes.
Related errors
- 打开 DMG 失败:{error}
- 当前平台不支持启动安装包
- invalid runtime file path
- missing cached {plugin} plugin for openai-bundled marketplac
- SetThreadDpiAwarenessContext failed
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/bfd51d570a2c23a3.
Report an issue: GitHub.