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_tokenView on GitHub (pinned to 88bb9c8533)
Solutions
- Set channels.matrix.user-id and channels.matrix.password, then restart: the next start wipes state and re-authenticates automatically.
- Or stop the agent and wipe manually (the path is printed in the error), then restart with a fresh access token.
- 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
- Provision user-id plus password on every long-running Matrix deployment, even when an access token is the primary auth.
- Back up the state directory so manual wipes are cheap.
- Rotate access tokens through a controlled restart, never by surprise mid-run.
- Treat this error as a paging event: the channel stays down until a human acts.
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
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- matrix: corruption recovery looped — aborting to avoid an in
- matrix login requires either access_token or user_id+passwor
- matrix: configured channels.matrix.user-id ({configured}) do
- matrix: configured channels.matrix.device-id ({configured})
- gateway registration failed ({status}): {err}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/0b2c340334a0c486.
Report an issue: GitHub.