BigPizzaV3/CodexPlusPlus · error · anyhow::Error

Remote Control session recovery requires launcher hooks…

Error message

Remote Control session recovery requires launcher hooks with codex-plus-data integration

What it means

This stub throws because Remote Control session recovery is not implemented in the launcher-holes-less build: `run_remote_control_session_recovery` is intentionally a `bail!` placeholder that documents the missing integration with the codex-plus-data persistence layer. Callers invoke it expecting session recovery, but the launcher binary was built without the data-layer hooks that store/restore session state. It is a guard against silently running recovery with no backend.

Solutions

  1. Build/wire the launcher with codex-plus-data integration enabled (enable the relevant feature/wiring so the stub is replaced by the real implementation)
  2. Check the call site: only invoke Remote Control session recovery when hooks are installed, or feature-gate the command in the UI/CLI
  3. Upgrade to a launcher build/version where the hook implementation is present

Example fix

// before
async fn run_remote_control_session_recovery(&self) -> anyhow::Result<()> {
    anyhow::bail!("Remote Control session recovery requires launcher hooks with codex-plus-data integration")
}
// after
async fn run_remote_control_session_recovery(&self) -> anyhow::Result<()> {
    let data = self.codex_plus_data().ok_or_else(|| anyhow::anyhow!("launcher hooks not installed"))?;
    data.recover_remote_control_sessions().await
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: check hook availability before invoking
if !launcher.has_codex_plus_data_hooks() {
    return Err(anyhow::anyhow!("Remote Control recovery unavailable: data hooks not installed"));
}

Type guard

fn hooks_installed(l: &Launcher) -> bool { l.codex_plus_data_handle().is_some() }

Try / catch

match launcher.run_remote_control_session_recovery().await {
    Ok(()) => {},
    Err(e) if e.to_string().contains("launcher hooks") => eprintln!("recovery unavailable in this build: {e}"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Any call path that reaches `run_remote_control_session_recovery` (e.g. CLI subcommand or manager UI invoking Remote Control recovery) when the launcher is compiled/wired without codex-plus-data integration.

Common situations: Running a slim/headless build of codex-plus-manager; using a stale launcher binary built before the data integration was enabled; invoking the recovery routine from a harness that did not install launcher hooks.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19). Data as JSON: /api/errors/bad9773c00fd8c74. Report an issue: GitHub.

Appendix: source

Thrown at crates/codex-plus-core/src/launcher.rs:715

        crate::ports::select_platform_loopback_port(requested)
    }

    async fn load_settings(&self) -> anyhow::Result<BackendSettings> {
        SettingsStore::default().load()
    }

    fn cleanup_unsupported_config(&self) -> anyhow::Result<()> {
        let home = crate::relay_config::default_codex_home_dir();
        crate::relay_config::cleanup_unsupported_approval_policies_in_home(&home)?;
        Ok(())
    }

    async fn run_provider_sync(&self) -> anyhow::Result<()> {
        anyhow::bail!("provider sync requires launcher hooks with codex-plus-data integration")
    }

    async fn run_remote_control_session_recovery(&self) -> anyhow::Result<()> {
        anyhow::bail!(
            "Remote Control session recovery requires launcher hooks with codex-plus-data integration"
        )
    }

    fn remote_control_session_recovery_is_safe_to_run(&self) -> bool {
        crate::watcher::find_session_index_cleanup_blocking_processes().is_empty()
    }

    async fn apply_active_relay_profile(&self, settings: &BackendSettings) -> anyhow::Result<()> {
        if !settings.relay_profiles_enabled {
            return Ok(());
        }
        let profile = settings.active_relay_profile();
        let home = crate::relay_config::default_codex_home_dir();
        let common_config = crate::relay_config::normalize_config_text(
            &[
                settings.relay_common_config_contents.as_str(),
                settings.relay_context_config_contents.as_str(),

View on GitHub (pinned to b1ed92e5e4)