{"record":{"id":"bfd51d570a2c23a3","repo":"BigPizzaV3/CodexPlusPlus","slug":"error-bfd51d","errorCode":null,"errorMessage":"启动安装包失败：{error}","messagePattern":"启动安装包失败：(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/update.rs","lineNumber":418,"sourceCode":"            || name.ends_with(\"setup.exe\")\n            || name.ends_with(\"installer.exe\"))\n}\n\nfn is_macos_installer_asset(name: &str) -> bool {\n    // Loose shape check; arch preference is handled by platform_asset_rank\n    // via is_macos_native_arch_asset.\n    name.contains(\"codex\") && name.contains(\"plus\") && name.ends_with(\".dmg\")\n}\n\npub fn launch_installer(path: &Path) -> anyhow::Result<()> {\n    #[cfg(windows)]\n    {\n        use std::os::windows::process::CommandExt;\n        std::process::Command::new(path)\n            .creation_flags(crate::windows_integration::CREATE_NO_WINDOW)\n            .spawn()\n            .map(|_| ())\n            .map_err(|error| anyhow::anyhow!(\"启动安装包失败：{error}\"))\n    }\n\n    #[cfg(target_os = \"macos\")]\n    {\n        std::process::Command::new(\"open\")\n            .arg(path)\n            .spawn()\n            .map(|_| ())\n            .map_err(|error| anyhow::anyhow!(\"打开 DMG 失败：{error}\"))\n    }\n\n    #[cfg(all(not(windows), not(target_os = \"macos\")))]\n    {\n        let _ = path;\n        anyhow::bail!(\"当前平台不支持启动安装包\")\n    }\n}\n","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/update.rs#L400-L436","documentation":"On Windows, launch_installer spawns the downloaded installer with std::process::Command::new(path) plus CREATE_NO_WINDOW. If the OS fails to spawn the process, the error is mapped to 启动安装包失败：{error} with the raw io::Error text embedded. Common io errors: file not found, access denied, or the file is not a valid executable.","triggerScenarios":"Calling perform_update on Windows when: the installer file was deleted/moved between download and launch; antivirus quarantined or blocked execution of the freshly downloaded .exe; the path contains characters the launcher mishandles; the downloaded file is corrupt or not a PE executable; insufficient permissions in the target directory.","commonSituations":"Windows Defender / SmartScreen marking the unsigned installer and blocking spawn; MSI vs NSIS mismatch causing 'not a valid Win32 application'; download truncated so the exe is corrupt; running from a temp dir cleaned concurrently.","solutions":["Read the embedded io error: NotFound → file missing; AccessDenied → AV/permissions; invalid exe → corrupt download.","Verify the installer file exists at the UpdateInstall/installer_path and re-download if missing.","Add the installer/URL to antivirus exclusions or whitelist the app if AV is blocking spawn.","Re-run perform_update to get a fresh, complete download (a corrupt/truncated file will also fail to spawn).","Launch the installer manually by double-clicking the downloaded file to isolate launcher vs installer problems."],"exampleFix":"// before\nlet install = perform_update(&release, &dir).await?;\n// after\nmatch perform_update(&release, &dir).await {\n    Ok(i) if i.launched => println!(\"installer started: {}\", i.installer_path.display()),\n    Ok(i) => println!(\"downloaded, run manually: {}\", i.installer_path.display()),\n    Err(e) if e.to_string().contains(\"启动安装包失败\") => {\n        eprintln!(\"spawn failed: {e}; run {} manually\", expected_path.display());\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"try-catch","validationCode":"fn installer_launchable(path: &std::path::Path) -> bool {\n    path.is_file() && std::fs::metadata(path).map_or(false, |m| m.len() > 0)\n}","typeGuard":null,"tryCatchPattern":"match perform_update(&release, &dir).await {\n    Ok(install) if install.launched => Ok(install),\n    Ok(install) => {\n        // launched == false on unsupported platforms; on Windows treat as manual install\n        open_in_explorer(&install.installer_path); Ok(install)\n    }\n    Err(e) if e.to_string().contains(\"启动安装包失败\") => {\n        eprintln!(\"spawn failed: {e}; instruct user to run the installer manually\");\n        Err(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Always surface installer_path to the user so a failed spawn can be completed manually.","Whitelist the app/installer in AV/SmartScreen policies on managed Windows machines.","Verify the downloaded file size before launch to avoid spawning truncated/corrupt exes.","Don't delete the temp download dir while the update flow is running."],"tags":["windows","process-spawn","installer","antivirus","update"],"backgroundTag":"command-not-found","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}