zeroclaw-labs/zeroclaw · error
client_cert is set but client_key is missing (both are requi
Error message
client_cert is set but client_key is missing (both are required for mutual TLS)
What it means
Broker mutual TLS on the AMQP channel needs a certificate/key pair. The validator requires `client_cert` and `client_key` to be supplied together; setting only `client_cert` produces an incomplete identity that could never complete an mTLS handshake, so the config is rejected up front.
Source
Thrown at crates/zeroclaw-config/src/schema.rs:16619
/// - at least one routing key is bound
pub fn validate(&self) -> anyhow::Result<()> {
let is_tls = self.amqp_url.starts_with("amqps://");
let is_plain = self.amqp_url.starts_with("amqp://");
if !is_tls && !is_plain {
anyhow::bail!(
"amqp_url must start with 'amqp://' or 'amqps://', got: {}",
self.amqp_url
);
}
if is_tls && self.ca_cert.is_none() {
anyhow::bail!("amqps:// requires ca_cert to verify the broker");
}
match (self.client_cert.is_some(), self.client_key.is_some()) {
(true, false) => {
anyhow::bail!(
"client_cert is set but client_key is missing (both are required for mutual TLS)"
)
}
(false, true) => {
anyhow::bail!(
"client_key is set but client_cert is missing (both are required for mutual TLS)"
)
}
_ => {}
}
if self.exchange.is_empty() {
validation_bail!(RequiredFieldEmpty, "exchange", "exchange must not be empty");
}
if self.routing_keys.is_empty() {
anyhow::bail!("at least one routing key must be configured");
}View on GitHub (pinned to 88bb9c8533)
Solutions
- Add the matching key: `client_key = "/etc/zeroclaw/client.key"`.
- Confirm both paths exist and the key matches the cert (`openssl x509 -noout -modulus` vs key modulus, or `openssl verify`).
- If mTLS is not needed, remove `client_cert` entirely (plain `amqps://` with just `ca_cert` is valid).
Example fix
# before client_cert = "/etc/zeroclaw/client.pem" # client_key missing # after client_cert = "/etc/zeroclaw/client.pem" client_key = "/etc/zeroclaw/client.key"
Defensive patterns
Strategy: validation
Validate before calling
anyhow::ensure!(
cfg.client_cert.is_some() == cfg.client_key.is_some(),
"client_cert and client_key must be set together"
); Type guard
fn mtls_pair_consistent(cert: &Option<PathBuf>, key: &Option<PathBuf>) -> bool {
cert.is_some() == key.is_some()
} Prevention
- Always edit client_cert and client_key as a pair.
- Verify the pair matches (openssl modulus check) after any rotation.
- If mTLS is unnecessary, omit both fields rather than one.
When it happens
Trigger: `client_cert = "/etc/zeroclaw/client.pem"` with no `client_key`; renaming or moving the key file and updating only the cert path; generating a new cert and forgetting to re-point the key.
Common situations: Setting up Fedora Messaging, which mandates client certificates; ops runbooks that rotate the cert but not the key path reference; copy-pasting half of an mTLS example block.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- client_key is set but client_cert is missing (both are requi
- amqp_url must start with 'amqp://' or 'amqps://', got: {}
- amqps:// requires ca_cert to verify the broker
- at least one routing key must be configured
- amqp channel '{}': client_cert is set but client_key is miss
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/00ffb44efdbf72b0.
Report an issue: GitHub.