{"record":{"id":"9d2063f014363c54","repo":"zeroclaw-labs/zeroclaw","slug":"at-least-one-routing-key-must-be-configured","errorCode":null,"errorMessage":"at least one routing key must be configured","messagePattern":"at least one routing key must be configured","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-config/src/schema.rs","lineNumber":16636,"sourceCode":"            (true, false) => {\n                anyhow::bail!(\n                    \"client_cert is set but client_key is missing (both are required for mutual TLS)\"\n                )\n            }\n            (false, true) => {\n                anyhow::bail!(\n                    \"client_key is set but client_cert is missing (both are required for mutual TLS)\"\n                )\n            }\n            _ => {}\n        }\n\n        if self.exchange.is_empty() {\n            validation_bail!(RequiredFieldEmpty, \"exchange\", \"exchange must not be empty\");\n        }\n\n        if self.routing_keys.is_empty() {\n            anyhow::bail!(\"at least one routing key must be configured\");\n        }\n\n        Ok(())\n    }\n}\n\nimpl ChannelConfig for AmqpConfig {\n    fn name() -> &'static str {\n        \"AMQP\"\n    }\n    fn desc() -> &'static str {\n        \"AMQP topic consumer\"\n    }\n}\n\nfn default_amqp_sender_label() -> String {\n    \"amqp\".to_string()\n}","sourceCodeStart":16618,"sourceCodeEnd":16654,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-config/src/schema.rs#L16618-L16654","documentation":"The AMQP consumer binds a queue to an exchange using one or more routing keys; `routing_keys` has a serde default of an empty vec, and validation requires at least one entry because a binding with no keys receives no deliveries. The exchange name itself is checked separately (non-empty) before this.","triggerScenarios":"A `[channels.amqp.<alias>]` block with `exchange` set but `routing_keys` omitted or set to `[]`; trimming keys while debugging bindings and reloading; migrating from queue-name-based consumers where routing keys do not exist.","commonSituations":"Configuring a Fedora Messaging or RabbitMQ topic exchange for the first time; expecting `#` (match-all) to be implicit — it is not, you must write `routing_keys = [\"#\"]`; templated configs where the keys array renders empty.","solutions":["Add at least one binding key, e.g. `routing_keys = [\"zeroclaw.events.#\"]` or the Fedora Messaging convention `org.fedoraproject.#`.","Use `#` explicitly if you intend to receive everything from the exchange.","Confirm the keys match what publishers set, otherwise the channel starts but stays silent."],"exampleFix":"# before\nexchange = \"events\"\nrouting_keys = []\n\n# after\nexchange = \"events\"\nrouting_keys = [\"zeroclaw.events.#\"]","handlingStrategy":"validation","validationCode":"anyhow::ensure!(\n    !cfg.routing_keys.is_empty(),\n    \"amqp channel needs at least one routing key binding\"\n);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Write `routing_keys = [\"#\"]` explicitly when you mean match-all.","After trimming keys during debugging, re-add at least one before reload.","Cross-check keys against what publishers actually set on the exchange."],"tags":["amqp","rabbitmq","config","routing-keys","required-field","zeroclaw"],"backgroundTag":"missing-required-config-field","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}