zeroclaw-labs/zeroclaw · error · anyhow::Error
amqp channel '{}': client_key is set but client_cert is miss
Error message
amqp channel '{}': client_key is set but client_cert is missing What it means
The mirror of the missing-key case: client_key is set but client_cert is missing. lapin builds a PKCS#12 identity from a certificate chain plus private key, so build_client_identity rejects the incomplete pair during connect with an error naming the channel alias.
Source
Thrown at crates/zeroclaw-channels/src/amqp.rs:288
cert_chain,
},
)
.await
.map_err(Into::into)
}
fn build_client_identity(&self) -> anyhow::Result<Option<OwnedIdentity>> {
let (cert_path, key_path) = match (&self.client_cert, &self.client_key) {
(Some(cert), Some(key)) => (cert, key),
(None, None) => return Ok(None),
(Some(_), None) => {
anyhow::bail!(
"amqp channel '{}': client_cert is set but client_key is missing",
self.alias
)
}
(None, Some(_)) => {
anyhow::bail!(
"amqp channel '{}': client_key is set but client_cert is missing",
self.alias
)
}
};
let cert_pem = std::fs::read(cert_path)?;
let key_pem = std::fs::read(key_path)?;
let der = pem_to_pkcs12_der(&cert_pem, &key_pem, &self.alias)?;
Ok(Some(OwnedIdentity {
der,
password: PKCS12_PASSWORD.to_string(),
}))
}
async fn establish_consumer(&self) -> anyhow::Result<(Connection, lapin::Consumer)> {
let conn = self.connect().await?;View on GitHub (pinned to 88bb9c8533)
Solutions
- Add the client_cert path pointing at the PEM certificate (leaf plus chain).
- Confirm both TLS files are present and readable; then restart the channel.
- If mTLS is not intended, remove client_key too so no client identity is attempted.
Example fix
# before [channels.amqp.prod] url = "amqps://broker:5671" client_key = "/etc/zeroclaw/tls/client.key" # after [channels.amqp.prod] url = "amqps://broker:5671" client_cert = "/etc/zeroclaw/tls/client.pem" client_key = "/etc/zeroclaw/tls/client.key"
Defensive patterns
Strategy: validation
Validate before calling
match (&cfg.client_cert, &cfg.client_key) {
(Some(_), None) | (None, Some(_)) => {
anyhow::bail!("client_cert and client_key must be set together");
}
_ => {}
} Type guard
fn has_complete_client_identity(cfg: &AmqpChannelConfig) -> bool {
cfg.client_cert.is_some() == cfg.client_key.is_some()
} Prevention
- Treat the TLS identity as one unit in config schemas and templates
- Fail config promotion when either half of the pair is missing
- Lint channel configs for half-configured mTLS in CI
When it happens
Trigger: AmqpChannelConfig sets client_key without client_cert — typically the cert path was dropped during config migration, templating, or environment promotion.
Common situations: Config generated from templates where the cert variable was empty; environments where the cert is managed differently from the key; manual edits adding the key first.
Related errors
- amqp channel '{}': client_cert is set but client_key is miss
- amqp channel '{alias}': client_cert contains no certificates
- amqp.{}: dispatch = {:?} routes to the SOP engine but no SOP
- ACP request_permission failed: {} ({})
- ACP request_permission timed out after {timeout:?}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/8f11a91fb9998b50.
Report an issue: GitHub.