zeroclaw-labs/zeroclaw · error · anyhow::Error
matrix: configure either `access_token` or `password`
Error message
matrix: configure either `access_token` or `password`
What it means
The Matrix channel constructor validates that at least one authentication credential is present: a non-blank `access_token` or a non-blank `password`. Both values are trimmed before the check, so whitespace-only counts as missing. The constructor fails fast rather than starting a listener that could never authenticate to the homeserver.
Source
Thrown at crates/zeroclaw-channels/src/matrix.rs:3998
pub fn new(
config: MatrixConfig,
alias: impl Into<String>,
peer_resolver: Arc<dyn Fn() -> Vec<String> + Send + Sync>,
state_dir: PathBuf,
) -> Result<Self> {
if config.homeserver.trim().is_empty() {
bail!("matrix: `homeserver` is required");
}
let has_token = config
.access_token
.as_deref()
.is_some_and(|t| !t.trim().is_empty());
let has_password = config
.password
.as_deref()
.is_some_and(|p| !p.trim().is_empty());
if !has_token && !has_password {
bail!("matrix: configure either `access_token` or `password`");
}
let ack_reactions = config.ack_reactions.unwrap_or(true);
let streaming_state = streaming::State::for_stream_mode(config.stream_mode);
Ok(Self {
config: Arc::new(config),
alias: alias.into(),
peer_resolver,
state_dir,
workspace_dir: None,
transcription: None,
client: tokio::sync::OnceCell::new(),
pending_approvals: Arc::new(TokioMutex::new(HashMap::new())),
streaming_state: Arc::new(TokioRwLock::new(streaming_state)),
threads_seen: Arc::new(TokioRwLock::new(HashSet::new())),
alias_cache: Arc::new(TokioRwLock::new(HashMap::new())),
reaction_log: Arc::new(TokioMutex::new(HashMap::new())),
bot_display_name: Arc::new(TokioRwLock::new(None)),
initial_sync_done: Arc::new(AtomicBool::new(false)),View on GitHub (pinned to 88bb9c8533)
Solutions
- Set `access_token` in `[channels.matrix.<alias>]` to a valid Matrix access token
- Or set `password` (with the bot username) so the channel can perform password login
- Check the key spelling (`access_token`, not `accessToken`) and remove surrounding whitespace-only values
- If the token comes from an env var, confirm the variable is exported and correctly referenced
Example fix
# before [channels.matrix.home] homeserver_url = "https://matrix.org" username = "@bot:matrix.org" # after [channels.matrix.home] homeserver_url = "https://matrix.org" username = "@bot:matrix.org" access_token = "syt_..." # or: password = "..."
Defensive patterns
Strategy: validation
Validate before calling
let m = &config.channels.matrix;
let has_auth = m
.access_token
.as_deref()
.is_some_and(|t| !t.trim().is_empty())
|| m.password.as_deref().is_some_and(|p| !p.trim().is_empty());
if !has_auth {
return Err(anyhow::anyhow!("matrix channel needs access_token or password"));
} Prevention
- Validate channel config blocks in a startup preflight before constructing any channel
- Run config through a schema/lint check in CI that flags matrix blocks without credentials
- Prefer access_token over password for long-running bots to avoid login-path failures
When it happens
Trigger: Constructing a Matrix channel (startup, config load of `[channels.matrix.<alias>]`, or programmatic `new`) with `access_token` absent/blank AND `password` absent/blank.
Common situations: New Matrix setup where only homeserver_url and username are filled in; token expected from an env var that is not set or not expanded; TOML key typo like `accessToken`; secret line lost when editing config.
Related errors
- matrix login requires either access_token or user_id+passwor
- Nextcloud Talk: no bot secret configured (set bot_token or w
- createSession failed ({status}): {body}
- matrix: {reason} Cannot auto-recover because channels.matrix
- matrix: configured channels.matrix.user-id ({configured}) do
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/450892d9a2d3be09.
Report an issue: GitHub.