BigPizzaV3/CodexPlusPlus · warning · anyhow::Error

periodic Runtime.evaluate reported unavailable capability

Error message

periodic Runtime.evaluate reported unavailable capability

What it means

run_periodic_evaluations polls the page on an interval by evaluating a capability-probe expression via Runtime.evaluate. If the expression evaluates to literal false (runtime_evaluate_result_is_false), the loop bails: the page itself reports that the required capability is absent, so periodic work stops by design.

Source

Thrown at crates/codex-plus-core/src/bridge.rs:167

{
    let socket = connect_cdp_websocket(websocket_url).await?;
    let mut session = CdpSession::new(socket);
    let mut interval = tokio::time::interval(period);
    loop {
        interval.tick().await;
        let Some(expression) = next_expression()? else {
            return Ok(());
        };
        let response = session
            .send_command(
                next_message_id(),
                "Runtime.evaluate",
                runtime_evaluate_params(&expression),
            )
            .await?;
        let response = ensure_runtime_evaluate_succeeded(response)?;
        if runtime_evaluate_result_is_false(&response) {
            bail!("periodic Runtime.evaluate reported unavailable capability");
        }
    }
}

pub async fn add_script_to_new_documents(
    websocket_url: &str,
    script: &str,
) -> anyhow::Result<Value> {
    let socket = connect_cdp_websocket(websocket_url).await?;
    let mut session = CdpSession::new(socket);
    session
        .send_command(
            1,
            "Page.addScriptToEvaluateOnNewDocument",
            json!({ "source": script }),
        )
        .await
}

View on GitHub (pinned to fb3ebd9a82)

Solutions

  1. Open the target page devtools and evaluate the same probe expression manually to see which capability is missing
  2. Update the desktop app to a version that ships the expected capability
  3. Confirm the websocket is attached to the correct page target (see pick_injectable_codex_page_target)
  4. Delay the first evaluation or tolerate a few consecutive false results before giving up

Example fix

// before - the first false result kills the loop
if runtime_evaluate_result_is_false(&response) {
    bail!("periodic Runtime.evaluate reported unavailable capability");
}

// after - tolerate transient false, stop only when stable
let mut false_streak = 0usize;
if runtime_evaluate_result_is_false(&response) {
    false_streak += 1;
    if false_streak >= 3 {
        bail!("periodic Runtime.evaluate reported unavailable capability");
    }
    continue;
}
false_streak = 0;
Defensive patterns

Strategy: fallback

Validate before calling

// One-shot capability probe before starting the periodic loop
let response = session.send_command(next_message_id(), "Runtime.evaluate",
    runtime_evaluate_params(&probe_expression)).await?;
if runtime_evaluate_result_is_false(&ensure_runtime_evaluate_succeeded(response)?) {
    return Ok(()); // capability absent: degrade silently instead of running the loop
}
run_periodic_evaluations(&ws_url, period, next_expression).await

Try / catch

if let Err(e) = run_periodic_evaluations(&ws_url, period, next_expr).await {
    if e.to_string().contains("unavailable capability") {
        tracing::info!("skin capability absent; periodic evaluation disabled");
    } else {
        return Err(e);
    }
}

Prevention

When it happens

Trigger: The probe expression (typically checking for a window API the injected feature depends on) returns false: an older app build without the API, the page navigated away or not yet finished loading its globals, or evaluation landing in a context where the global is missing.

Common situations: The desktop app version is older than the manager expects; timing - the first evaluation fires before page load completes; the capability is disabled in the target build.

Related errors


AI-assisted analysis of BigPizzaV3/CodexPlusPlus@fb3ebd9a82 (2026-08-17). Data as JSON: /api/errors/8242f9e1944e8386. Report an issue: GitHub.