BigPizzaV3/CodexPlusPlus · error · anyhow::Error
Remote Control session recovery is unavailable
Error message
Remote Control session recovery is unavailable
What it means
recover_remote_control_session has a default implementation on the BridgeDataService trait that always bails with 'Remote Control session recovery is unavailable'. The bridge route '/remote-control-session/recover' dispatches to ctx.data.recover_remote_control_session(thread_id), so the error surfaces when the installed data service does not override the default — i.e. the runtime build has no remote-control backend wired in.
Source
Thrown at crates/codex-plus-core/src/routes.rs:124
#[async_trait]
pub trait BridgeDataService: Send + Sync {
async fn delete(&self, session: SessionRef) -> anyhow::Result<DeleteResult>;
async fn undo(&self, undo_token: String) -> anyhow::Result<DeleteResult>;
async fn export_markdown(&self, session: SessionRef) -> anyhow::Result<ExportResult>;
async fn thread_usage_history(&self, session: SessionRef) -> anyhow::Result<Value>;
async fn find_archived_thread_by_title(
&self,
title: String,
) -> anyhow::Result<Option<SessionRef>>;
async fn move_thread_workspace(
&self,
session: SessionRef,
target_cwd: String,
) -> anyhow::Result<Value>;
async fn thread_sort_key(&self, session: SessionRef) -> anyhow::Result<Value>;
async fn thread_sort_keys(&self, sessions: Vec<SessionRef>) -> anyhow::Result<Value>;
async fn recover_remote_control_session(&self, _thread_id: String) -> anyhow::Result<Value> {
anyhow::bail!("Remote Control session recovery is unavailable")
}
}
pub async fn handle_bridge_request(
ctx: BridgeContext,
path: &str,
payload: Value,
) -> serde_json::Value {
let started = Instant::now();
let _ = crate::diagnostic_log::append_diagnostic_log(
"bridge.request",
json!({
"path": path,
"payload_keys": payload
.as_object()
.map(|object| object.keys().cloned().collect::<Vec<_>>())
.unwrap_or_default()
}),View on GitHub (pinned to 1f431ae49b)
Solutions
- Provide a real implementation of recover_remote_control_session in your BridgeDataService impl (the production impl already does this — use it instead of a stub)
- Check capability before calling: only invoke '/remote-control-session/recover' on builds known to support it, and hide the UI action otherwise
- If embedding, route the BridgeContext through the core data service rather than a Default-based stub
- Treat the error message as a capability probe: on this specific message, disable the feature instead of retrying
Example fix
// before
struct MyDataService;
#[async_trait]
impl BridgeDataService for MyDataService { /* required methods only */ }
// after
struct MyDataService;
#[async_trait]
impl BridgeDataService for MyDataService {
async fn recover_remote_control_session(&self, thread_id: String) -> anyhow::Result<Value> {
crate::remote_control_recovery::recover(&self.store, &thread_id).await
}
/* required methods */
} Defensive patterns
Strategy: fallback
Try / catch
let value = match ctx.data.recover_remote_control_session(thread_id).await {
Ok(v) => v,
Err(e) if e.to_string().contains("recovery is unavailable") => {
json!({"status": "failed", "supported": false}) // hide the feature, do not retry
}
Err(e) => return Err(e),
}; Prevention
- Expose a capability flag (e.g. supported_paths) from the service and have the frontend disable the button
- In embedded builds, always route BridgeContext through the production data service instead of a stub impl
- Treat this exact message as a permanent condition: never retry it
When it happens
Trigger: Sending a bridge request to path '/remote-control-session/recover' with payload field 'thread_id' (or 'threadId') while the BridgeDataService implementation behind BridgeContext.data uses the trait default (never overrides recover_remote_control_session). handle_bridge_request converts the bail into a failed response via failed_from_error.
Common situations: Embedding codex-plus-core with a minimal/test BridgeDataService that implements only the required trait methods; running a CoreRuntimeService wiring where the remote-control feature is disabled at compile time or behind a feature flag; frontend calling the endpoint on an older build that predates the feature.
Related errors
- Remote Control recovery requires a valid thread id
- Remote Control recovery requires profile and provider proven
- Remote Control session recovery requires launcher hooks with
- Codex injection failed
- 中转 Key 不能为空
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/3465bc7e8a91292d.
Report an issue: GitHub.