zeroclaw-labs/zeroclaw · critical

exceeded {} reconnect attempts, giving up

Error message

exceeded {} reconnect attempts, giving up

What it means

`listen()` runs a reconnect state machine: on each disconnect it retries with exponential backoff (base 3s, doubling, capped at 300s) for up to `MAX_RETRIES` (10) attempts. When the counter reports `exceeded`, the loop gives up and `listen()` returns this error — the channel stays down until something restarts it. Session files are purged only when an explicit LoggedOut was observed, so reaching this error usually means repeated transient failures (network, protocol) or repeated forced logouts.

Source

Thrown at crates/zeroclaw-channels/src/whatsapp_web.rs:2995

            let handle = self.bot_handle.lock().take();
            if let Some(handle) = handle {
                handle.abort();
                // Await the aborted task so background I/O finishes before
                // we delete session files.
                let _ = handle.await;
            }

            // Drop bot/device so the SQLite connection is closed
            // before we remove session files (releases WAL/SHM locks).
            // `backend` was moved into the builder, so dropping `bot`
            // releases the last Arc reference to the storage backend.
            drop(bot);
            drop(device);

            if should_reconnect {
                let (attempts, exceeded) = Self::record_retry(&retry_count);
                if exceeded {
                    anyhow::bail!(
                        "exceeded {} reconnect attempts, giving up",
                        Self::MAX_RETRIES
                    );
                }

                // Only purge session files when LoggedOut was explicitly observed.
                // A transient task crash (Err from recv) should not wipe a valid session.
                if Self::should_purge_session(&session_revoked) {
                    for path in Self::session_file_paths(&expanded_session_path) {
                        match tokio::fs::remove_file(&path).await {
                            Ok(()) => {}
                            Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
                            Err(e) => ::zeroclaw_log::record!(
                                WARN,
                                ::zeroclaw_log::Event::new(
                                    module_path!(),
                                    ::zeroclaw_log::Action::Note
                                )

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Check the zeroclaw logs immediately before the give-up to identify the disconnect cause (LoggedOut vs task crash vs network).
  2. Restore connectivity and restart the process or `listen()` — the attempt counter resets on restart.
  3. If LoggedOut repeats, delete the session files and re-pair by scanning the QR.
  4. Keep zeroclaw updated so the vendored WhatsApp Web backend tracks protocol changes.

Example fix

// before: run listen() once; the process gives up after 10 failed reconnects
if let Err(e) = channel.listen(tx).await {
    tracing::error!("channel died: {e}");
}

// after: supervise with restart so the retry counter resets
loop {
    if let Err(e) = channel.listen(tx.clone()).await {
        tracing::error!("whatsapp-web listen failed: {e}; restarting in 60s");
        tokio::time::sleep(std::time::Duration::from_secs(60)).await;
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// Check link health before a long-running shift; restart listen() if it already gave up
if !channel.health_check().await {
    // the listen task may have exhausted its 10 reconnect attempts
    restart_channel_task(&channel, tx).await;
}

Try / catch

loop {
    if let Err(e) = channel.listen(tx.clone()).await {
        if e.to_string().contains("reconnect attempts, giving up") {
            tracing::error!("whatsapp-web gave up reconnecting: {e}; restarting in 60s");
            tokio::time::sleep(std::time::Duration::from_secs(60)).await;
            continue; // fresh listen() resets the attempt counter
        }
        return Err(e);
    }
}

Prevention

When it happens

Trigger: Ten consecutive reconnect failures: a prolonged network outage, WhatsApp protocol/backend incompatibility, the phone number being re-linked elsewhere (forcing logout every reconnect), or the bot task crashing on startup repeatedly.

Common situations: Server losing network overnight; another device linking the same number and invalidating the session each time; version skew with the WhatsApp Web protocol after an update.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/99126615445c7495. Report an issue: GitHub.