{"record":{"id":"a5fa90b78c509b43","repo":"BigPizzaV3/CodexPlusPlus","slug":"macos-open-command-is-empty","errorCode":null,"errorMessage":"macOS open command is empty","messagePattern":"macOS open command is empty","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/launcher.rs","lineNumber":786,"sourceCode":"        if app_dir.extension().and_then(|value| value.to_str()) == Some(\"app\") {\n            let cleanup_policy = if is_macos_app_running(app_dir).await {\n                MacosCleanupPolicy::SkipQuitBecauseAlreadyRunning\n            } else {\n                MacosCleanupPolicy::QuitIfNotPreviouslyRunning\n            };\n            let command = if let Some(inspector_port) = native_menu_inspector_port {\n                build_macos_open_command_with_native_menu_inspector(\n                    app_dir,\n                    debug_port,\n                    inspector_port,\n                    &launch_extra_args,\n                )\n            } else {\n                build_macos_open_command(app_dir, debug_port, &launch_extra_args)\n            };\n            let executable = command\n                .first()\n                .ok_or_else(|| anyhow::anyhow!(\"macOS open command is empty\"))?;\n            let child = Command::new(executable)\n                .args(&command[1..])\n                .stdout(Stdio::null())\n                .stderr(Stdio::null())\n                .spawn()\n                .context(\"failed to launch macOS Codex app\")?;\n            *self.child.lock().await = Some(child);\n            if let Some(inspector_port) = native_menu_inspector_port {\n                start_native_menu_localizer(inspector_port);\n            }\n            return Ok(CodexLaunch::Process {\n                command,\n                wait_strategy: ProcessWaitStrategy::ExternalWaitCommand,\n                macos_cleanup_policy: Some(cleanup_policy),\n            });\n        }\n\n        let command = if let Some(inspector_port) = native_menu_inspector_port {","sourceCodeStart":768,"sourceCodeEnd":804,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/1f431ae49b57b3055e0e6845ba6156c6b4232b4d/crates/codex-plus-core/src/launcher.rs#L768-L804","documentation":"On macOS, when the resolved app_dir ends in .app the launcher builds an `open`-style argv via build_macos_open_command (or its native-menu-inspector variant) and guards that the vector is non-empty before Command::new (crates/codex-plus-core/src/launcher.rs:784-786). The builders always seed the vector with the open executable path, so an empty command indicates a broken builder invocation (custom build_macos_open_command_* override, bad refactor, or empty app_dir producing degenerate output) rather than a normal runtime condition.","triggerScenarios":"app_dir has extension \"app\", is_macos launch branch is taken, and build_macos_open_command / build_macos_open_command_with_native_menu_inspector returns a Vec with zero elements — e.g. after a refactor that conditionally skips pushing the executable, or a copied/modified builder in a fork.","commonSituations":"Fork modifications to the macOS command builders; passing an empty Path as app_dir so path formatting yields nothing; regression after changing build_macos_open_command's return construction; this is effectively an unreachable defensive invariant in stock builds.","solutions":["If you forked or wrapped build_macos_open_command*, restore the unconditional first element (the `open` executable) so the vec is never empty","Check the resolved app_dir is non-empty and has extension .app before launch; a malformed dir points at an upstream app-path resolution problem","If unreachable in your build, treat as an assertion failure: report the full settings/app_dir used and file it upstream rather than catching it"],"exampleFix":"// before\nfn build_macos_open_command(app_dir: &Path, debug_port: u16, extra: &[String]) -> Vec<String> {\n    let mut command = Vec::new(); // may stay empty\n    ...\n}\n\n// after\nfn build_macos_open_command(app_dir: &Path, debug_port: u16, extra: &[String]) -> Vec<String> {\n    let mut command = vec![\"/usr/bin/open\".to_string()]; // never empty\n    ...\n}","handlingStrategy":"validation","validationCode":"// Before launch, sanity-check the macOS branch inputs\n#[cfg(target_os = \"macos\")]\nfn macos_launch_ready(app_dir: &Path) -> bool {\n    app_dir.extension().and_then(|e| e.to_str()) == Some(\"app\")\n        && app_dir.join(\"Contents/MacOS\").is_dir()\n}","typeGuard":"fn non_empty_command(cmd: &[String]) -> bool {\n    cmd.first().is_some_and(|exe| !exe.trim().is_empty())\n}","tryCatchPattern":"// Guard is an invariant; if it ever fires, capture diagnostics rather than retry:\nErr(e) if e.to_string() == \"macOS open command is empty\" => {\n    anyhow::bail!(\"internal invariant broken: builder returned empty argv for {}\", app_dir.display())\n}","preventionTips":["Never modify build_macos_open_command* to conditionally omit the executable element","Unit-test builders: assert !build_macos_open_command(app_dir, port, &[]).is_empty()","Validate app_dir resolves to a real .app bundle before invoking launch"],"tags":["rust","macos","launcher","command-construction","defensive-check"],"backgroundTag":"empty-command-invocation","analyzedSha":"1f431ae49b57b3055e0e6845ba6156c6b4232b4d","analyzedAt":"2026-08-16T20:54:18.598Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}