{"record":{"id":"ad25599601d1a7b8","repo":"zeroclaw-labs/zeroclaw","slug":"matrix-homeserver-is-required","errorCode":null,"errorMessage":"matrix: `homeserver` is required","messagePattern":"matrix: `homeserver` is required","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/matrix.rs","lineNumber":3987,"sourceCode":"    undecryptable_seen: Arc<TokioMutex<HashSet<OwnedEventId>>>,\n    /// Resolved `ack_reactions` for this Matrix instance — the\n    /// per-channel `MatrixConfig.ack_reactions` override falls back to\n    /// `[channels].ack_reactions` here at construction time, so the\n    /// read site doesn't need to re-resolve on every reaction.\n    ack_reactions: bool,\n}\n\nimpl MatrixChannel {\n    /// Validate config and prepare the channel. The SDK Client is built lazily\n    /// on first `listen()` or `send()` call.\n    pub fn new(\n        config: MatrixConfig,\n        alias: impl Into<String>,\n        peer_resolver: Arc<dyn Fn() -> Vec<String> + Send + Sync>,\n        state_dir: PathBuf,\n    ) -> Result<Self> {\n        if config.homeserver.trim().is_empty() {\n            bail!(\"matrix: `homeserver` is required\");\n        }\n        let has_token = config\n            .access_token\n            .as_deref()\n            .is_some_and(|t| !t.trim().is_empty());\n        let has_password = config\n            .password\n            .as_deref()\n            .is_some_and(|p| !p.trim().is_empty());\n        if !has_token && !has_password {\n            bail!(\"matrix: configure either `access_token` or `password`\");\n        }\n        let ack_reactions = config.ack_reactions.unwrap_or(true);\n        let streaming_state = streaming::State::for_stream_mode(config.stream_mode);\n        Ok(Self {\n            config: Arc::new(config),\n            alias: alias.into(),\n            peer_resolver,","sourceCodeStart":3969,"sourceCodeEnd":4005,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/matrix.rs#L3969-L4005","documentation":"The Matrix channel constructor validates config up front: channels.matrix.homeserver must be a non-empty, non-whitespace string, because every SDK call (login, sync, send) needs the homeserver base URL. An empty homeserver aborts construction immediately, before any login attempt - even when an access token is configured, since a token does not imply a server.","triggerScenarios":"Constructing the Matrix channel with channels.matrix.homeserver absent, empty, or whitespace-only - typically an env-var interpolation (e.g. ${MATRIX_HOMESERVER}) that produced an empty string, or a misspelled/removed config key.","commonSituations":"New deployment with homeserver forgotten; templating emitting \"\" for unset variables; config key renamed across a ZeroClaw upgrade; local dev config trimmed down too far.","solutions":["Set channels.matrix.homeserver to the homeserver's client API base, e.g. https://matrix.example.org.","Check the rendered config for empty values from unset environment variables - the trim check makes whitespace count as missing.","Homeserver is mandatory in every auth mode (token or password); it cannot be omitted in favor of access_token.","Add a config lint that fails builds when required Matrix keys are blank."],"exampleFix":"# before\n[channels.matrix]\naccess-token = \"syt_...\"\n\n# after\n[channels.matrix]\nhomeserver = \"https://matrix.example.org\"\naccess-token = \"syt_...\"","handlingStrategy":"validation","validationCode":"fn homeserver_configured(cfg: &MatrixConfig) -> bool {\n    !cfg.homeserver.trim().is_empty()\n}\n\nassert!(homeserver_configured(&config), \"channels.matrix.homeserver is required\");","typeGuard":"fn required_homeserver(cfg: &MatrixConfig) -> Option<&str> {\n    let h = cfg.homeserver.trim();\n    (!h.is_empty()).then_some(h)\n}","tryCatchPattern":null,"preventionTips":["Fail fast on config load: validate all required Matrix keys, homeserver first, before constructing channels.","Render configs in strict mode so unset variables error instead of emitting empty strings.","Keep a minimal known-good config in the repo and diff deployments against it."],"tags":["matrix","config","homeserver","validation","startup"],"backgroundTag":"missing-required-config","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}