{"record":{"id":"6f01a206c08522f1","repo":"stalwartlabs/stalwart","slug":"cluster-subscribererror-6f01a2","errorCode":null,"errorMessage":"Cluster::SubscriberError","messagePattern":"Cluster::SubscriberError","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/coordinator/src/backend/zenoh/pubsub.rs","lineNumber":34,"sourceCode":"    pub async fn publish(&self, topic: &'static str, message: Vec<u8>) -> trc::Result<()> {\n        self.session\n            .declare_publisher(topic)\n            .await\n            .map_err(|err| {\n                Error::new(EventType::Cluster(ClusterEvent::PublisherError)).reason(err)\n            })?\n            .put(message)\n            .await\n            .map_err(|err| Error::new(EventType::Cluster(ClusterEvent::PublisherError)).reason(err))\n    }\n\n    pub async fn subscribe(&self, topic: &'static str) -> trc::Result<PubSubStream> {\n        self.session\n            .declare_subscriber(topic)\n            .await\n            .map(|subs| PubSubStream::Zenoh(ZenohPubSubStream { subs }))\n            .map_err(|err| {\n                Error::new(EventType::Cluster(ClusterEvent::SubscriberError)).reason(err)\n            })\n    }\n}\n\nimpl ZenohPubSubStream {\n    pub async fn next(&mut self) -> Option<Msg> {\n        self.subs\n            .recv_async()\n            .await\n            .map(|sample| Msg::Zenoh(sample.payload().to_bytes().into_owned()))\n            .ok()\n    }\n}\n","sourceCodeStart":16,"sourceCodeEnd":48,"githubUrl":"https://github.com/stalwartlabs/stalwart/blob/e96200385781a6a9995a8b839ac27d6c75a983ee/crates/coordinator/src/backend/zenoh/pubsub.rs#L16-L48","documentation":"The Zenoh backend raises Cluster::SubscriberError when `session.declare_subscriber(topic)` fails while creating a subscription for the given key expression. The zenoh error is wrapped into a trc::Error tagged Cluster::SubscriberError.","triggerScenarios":"Calling `ZenohPubSub::subscribe(topic)` where `declare_subscriber(topic).await` returns Err — invalid key expression or a dead/closed session.","commonSituations":"Malformed key expression (empty, spaces, bad selectors); subscribing after the Zenoh session closed; Zenoh config pointing at an unreachable router so the session is unusable.","solutions":["Check the attached reason for the exact zenoh declare_subscriber error.","Validate the topic as a Zenoh key expression (non-empty, valid characters, correct selector syntax if using wildcards).","Ensure the session is open before subscribing and handle reconnects.","Review the Zenoh session config (mode, locators, scouting) if the session itself is failing."],"exampleFix":"// before\nlet subs = session.declare_subscriber(\"\").await?; // empty key\n// after\nlet subs = session.declare_subscriber(\"cluster/events\").await?;","handlingStrategy":"validation","validationCode":"fn is_valid_zenoh_key(k: &str) -> bool {\n    !k.is_empty()\n        && !k.contains(char::is_whitespace)\n        && k.split('/').all(|seg| !seg.contains(['?', '#', '[', ']']))\n}","typeGuard":null,"tryCatchPattern":"match zenoh.subscribe(topic).await {\n    Ok(stream) => stream,\n    Err(e) => {\n        tracing::error!(topic, reason = ?e.reason(), \"zenoh declare_subscriber failed\");\n        return Err(e);\n    }\n}","preventionTips":["Validate key expressions (including wildcards) before declare_subscriber.","Subscribe only while the session is open; drop subscribers before closing the session.","Handle reconnects by re-declaring subscribers."],"tags":["zenoh","pubsub","subscriber","key-expression"],"backgroundTag":"invalid-argument-value","analyzedSha":"e96200385781a6a9995a8b839ac27d6c75a983ee","analyzedAt":"2026-09-06T22:07:17.982Z","contentChangedAt":"2026-09-06T22:07:17.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}