zeroclaw-labs/zeroclaw · critical · anyhow::Error
matrix: corruption recovery looped — aborting to avoid an in
Error message
matrix: corruption recovery looped — aborting to avoid an infinite restart cycle. Wipe ~/.zeroclaw/state/matrix/ manually and restart.
What it means
Matrix client startup wraps session loading in bounded auto-recovery: corrupted persisted state triggers a wipe of the state directory plus a fresh login, retried via build_attempt with a recovery_attempts counter. Anything above 1 aborts with this message - a hard recursion bound so a wipe-then-relogin cycle cannot loop forever. Seeing it means corruption (or a login failure indistinguishable from it) recurred even after the automatic wipe already ran once.
Source
Thrown at crates/zeroclaw-channels/src/matrix.rs:1329
blob: &session::SessionBlob,
) -> bool {
let Some(want) = config.user_id.as_deref().filter(|s| !s.is_empty()) else {
return false;
};
if !want.contains(':') {
return false;
}
want != blob.user_id.as_str()
}
async fn build_attempt(
config: &MatrixConfig,
state_dir: &Path,
recovery_attempts: u32,
) -> Result<Client> {
// Hard recursion bound: at most one auto-wipe + relogin cycle per call.
if recovery_attempts > 1 {
bail!(
"matrix: corruption recovery looped — aborting to avoid an infinite restart cycle. \
Wipe ~/.zeroclaw/state/matrix/ manually and restart."
);
}
let saved = session::load(state_dir)?;
// A saved session that belongs to a different account would run this
// channel block as the wrong Matrix identity. Wipe and re-login fresh
// under the configured account instead of impersonating.
if let Some(blob) = saved.as_ref()
&& saved_session_is_foreign(config, blob)
{
return recover_or_bail(
config,
state_dir,
recovery_attempts,
&format!(View on GitHub (pinned to 88bb9c8533)
Solutions
- Stop the agent and wipe the state directory manually, as the message says: rm -rf ~/.zeroclaw/state/matrix/ , then restart.
- If it recurs after a manual wipe, check disk health and free space on the volume backing the state dir - a failing or full disk re-corrupts every new session.
- Verify the homeserver is reachable and credentials are valid so the fresh login after the wipe succeeds (set channels.matrix.user-id and password).
- On containers, ensure the state volume is persistent and writable, and the clock is NTP-synced.
Defensive patterns
Strategy: fallback
Try / catch
match build_matrix_client(&config, &state_dir, 0).await {
Ok(client) => client,
Err(err) if err.to_string().contains("corruption recovery looped") => {
// escalate to the operator instead of restarting: a naive supervisor
// would re-trigger the same wipe/relogin loop
shutdown_with_alert("matrix state dir needs manual wipe", &state_dir);
return Err(err);
}
Err(err) => return Err(err),
} Prevention
- Run the state dir on a persistent, healthy volume; monitor free space and disk errors.
- Configure channels.matrix.user-id and password so auto-recovery can re-authenticate after a wipe.
- Do not use a naive restart-on-exit supervisor against this error - alert a human instead.
- Keep system clocks NTP-synced; skewed clocks can invalidate freshly minted sessions.
When it happens
Trigger: Starting the Matrix channel when the persisted session under the state_dir is corrupted; build_attempt wipes state and re-logins (recovery_attempts 0 to 1), and the freshly created session fails or corrupts again, so the recursive attempt sees recovery_attempts > 1.
Common situations: Disk/filesystem problems or a full disk repeatedly truncating session files; a homeserver that keeps invalidating the new session (forced password change, security policy); containers remounting a broken or non-persistent state volume; clock skew making fresh sessions look invalid.
Related errors
- matrix: {reason} Cannot auto-recover because channels.matrix
- matrix: draft message id is empty
- matrix: partial draft state unavailable
- matrix: single-message draft state unavailable
- matrix: multi-message draft state unavailable
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/5021282d2d72fbb6.
Report an issue: GitHub.