zeroclaw-labs/zeroclaw · critical · anyhow::Error

matrix: {reason} Cannot auto-recover because channels.matrix

Error message

matrix: {reason}
Cannot auto-recover because channels.matrix.password and channels.matrix.user-id are not both set.
Either:
  • configure channels.matrix.password (and user-id) so the next start can re-authenticate, or
  • wipe the state directory manually:  rm -rf {}

What it means

When Matrix startup hits a session failure it can auto-recover by wiping the state directory and logging in again, but re-authentication requires channels.matrix.user-id and channels.matrix.password. On an access-token-only deployment there is no way to re-login after a wipe, so instead of destroying session state it cannot rebuild, the channel refuses and reports the underlying reason plus the two remedies: add password credentials, or wipe manually.

Source

Thrown at crates/zeroclaw-channels/src/matrix.rs:1504

        config: &MatrixConfig,
        state_dir: &Path,
        recovery_attempts: u32,
        reason: &str,
    ) -> Result<Client> {
        if can_password_relogin(config) {
            ::zeroclaw_log::record!(
                WARN,
                ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
                    .with_outcome(::zeroclaw_log::EventOutcome::Unknown),
                &format!(
                    "matrix: {reason} Auto-recovering: wiping {} and re-authenticating with password.",
                    state_dir.display()
                )
            );
            wipe_state(state_dir)?;
            return Box::pin(build_attempt(config, state_dir, recovery_attempts + 1)).await;
        }
        bail!(
            "matrix: {reason}\n\
             Cannot auto-recover because channels.matrix.password and channels.matrix.user-id are not both set.\n\
             Either:\n  \
             • configure channels.matrix.password (and user-id) so the next start can re-authenticate, or\n  \
             • wipe the state directory manually:  rm -rf {}",
            state_dir.display(),
        );
    }

    async fn login_fresh(client: &Client, config: &MatrixConfig) -> Result<()> {
        // Prefer password when set: it creates a server-side device matching
        // `config.device_id`, so subsequent crypto operations don't fight with
        // a token bound to a different device.
        if let Some(pw) = config.password.as_deref().filter(|s| !s.is_empty()) {
            return password_login(client, config, pw).await;
        }
        if config
            .access_token

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Set channels.matrix.user-id and channels.matrix.password, then restart: the next start wipes state and re-authenticates automatically.
  2. Or stop the agent and wipe manually (the path is printed in the error), then restart with a fresh access token.
  3. Keep user-id plus password configured long-term so future session corruption self-heals instead of halting the channel.

Example fix

# before: token-only - no relogin possible after session corruption
[channels.matrix]
homeserver = "https://matrix.example.org"
access-token = "syt_..."

# after: recovery credentials present
[channels.matrix]
homeserver = "https://matrix.example.org"
user-id = "@bot:example.org"
password = "correct-horse-battery"
Defensive patterns

Strategy: validation

Validate before calling

// At deploy time: assert the channel can re-authenticate after a session wipe.
fn can_auto_recover(cfg: &MatrixConfig) -> bool {
    cfg.user_id.as_deref().is_some_and(|u| !u.trim().is_empty())
        && cfg.password.as_deref().is_some_and(|p| !p.is_empty())
}
if !can_auto_recover(&config) {
    tracing::warn!("matrix: no relogin credentials; a corrupted session will halt the channel until the state dir is wiped manually");
}

Prevention

When it happens

Trigger: Starting the Matrix channel when persisted session state fails to load or validate (the {reason} prefix) while config provides access_token only - password and user-id are not both set, so the auto-wipe-and-relogin path is unavailable.

Common situations: Access token revoked (logout-all, password change) or session file corrupted on a headless deployment provisioned with just a token; migrating hosts with a stale state dir; initial setup where only homeserver and token were filled in.

Understand the failure class

Related errors


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