Kuberwastaken/claurst · error

No active Chrome session. Run `/chrome connect` first.

Error message

No active Chrome session. Run `/chrome connect` first.

What it means

Thrown by `take_session` in src-rust/crates/commands/src/chrome.rs when no Chrome session is stored in the global SESSION mutex. Commands like navigate, screenshot, click, fill, and eval call take_session to pop the session from the global slot; `.take()` returns None when `connect` was never run or the session was not put back. The library requires an explicit `/chrome connect` step before any CDP operation.

Solutions

  1. Run `/chrome connect` first so a session is stored in the global slot.
  2. Ensure the Chrome binary is running with the remote debugging port before connecting.
  3. In code, check for an active session (or call connect) before invoking navigate/screenshot/click/fill/eval.

Example fix

// before
/chrome navigate https://example.com
// error: No active Chrome session

// after
/chrome connect
/chrome navigate https://example.com
Defensive patterns

Strategy: validation

Validate before calling

// check the global session slot before running a command
if !chrome::has_active_session() {
    chrome::connect(port)?;
}

Type guard

fn has_session(s: &Option<ChromeSession>) -> bool { s.is_some() }

Try / catch

match take_session() {
    Ok(s) => operate(s),
    Err(_) => connect_and_retry(),
}

Prevention

When it happens

Trigger: Calling any Chrome command (navigate, screenshot, click, fill, eval) before `/chrome connect` has stored a ChromeSession in the global SESSION slot.

Common situations: Fresh app start where the user issues `/chrome navigate` first; a previous session was consumed/failed and never restored; Chrome was closed between commands and session teardown removed it; a script calls subcommands out of order.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/c953237e103b07b5. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/commands/src/chrome.rs:100

                    return Err(anyhow::anyhow!("CDP error: {}", err));
                }
                return Ok(val);
            }
            // It's an event or different response — keep waiting.
        }
    }

    // -----------------------------------------------------------------------
    // Session take/restore helpers
    //
    // We avoid holding a MutexGuard across await points by taking ownership
    // of the session, performing all async operations with it, then putting
    // it back into the global.
    // -----------------------------------------------------------------------

    fn take_session() -> anyhow::Result<ChromeSession> {
        SESSION.lock().take().ok_or_else(|| {
            anyhow::anyhow!("No active Chrome session. Run `/chrome connect` first.")
        })
    }

    fn store_session(s: ChromeSession) {
        *SESSION.lock() = Some(s);
    }

    // -----------------------------------------------------------------------
    // Public helpers called from the SlashCommand impl
    // -----------------------------------------------------------------------

    /// Connect to Chrome at the given port.
    /// Picks the first available target (tab/page).
    pub async fn connect(port: u16) -> anyhow::Result<String> {
        let http_url = format!("http://localhost:{}/json/list", port);
        let client = reqwest::Client::builder()
            .timeout(std::time::Duration::from_secs(3))
            .build()?;

View on GitHub (pinned to b0637c97ec)