{"record":{"id":"8686433456658423","repo":"zeroclaw-labs/zeroclaw","slug":"amqp-channel-alias-client-cert-contains-no-ce","errorCode":null,"errorMessage":"amqp channel '{alias}': client_cert contains no certificates","messagePattern":"amqp channel '(.+?)': client_cert contains no certificates","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/amqp.rs","lineNumber":382,"sourceCode":"}\n\n/// Ephemeral password protecting the in-memory PKCSidentity. The bundle is\n/// built and consumed within a single connect call and never persisted, so the\n/// password only has to round-trip through tcp-stream's PKCSreader.\nconst PKCS12_PASSWORD: &str = \"zeroclaw-amqp\";\n\n/// Convert a PEM client certificate chain and private key into a PKCSDER\n/// bundle suitable for tcp-stream's rustls client-auth path.\nfn pem_to_pkcs12_der(cert_pem: &[u8], key_pem: &[u8], alias: &str) -> anyhow::Result<Vec<u8>> {\n    use p12_keystore::{Certificate, KeyStore, KeyStoreEntry, PrivateKeyChain};\n\n    let certs: Vec<Vec<u8>> = rustls_pemfile::certs(&mut &cert_pem[..])\n        .collect::<Result<Vec<_>, _>>()?\n        .into_iter()\n        .map(|c| c.as_ref().to_vec())\n        .collect();\n    if certs.is_empty() {\n        anyhow::bail!(\"amqp channel '{alias}': client_cert contains no certificates\");\n    }\n\n    let key = rustls_pemfile::private_key(&mut &key_pem[..])?.ok_or_else(|| {\n        anyhow::Error::msg(format!(\n            \"amqp channel '{alias}': client_key contains no private key\"\n        ))\n    })?;\n\n    let chain: Vec<Certificate> = certs\n        .iter()\n        .map(|der| Certificate::from_der(der))\n        .collect::<Result<_, _>>()\n        .map_err(|e| {\n            anyhow::Error::msg(format!(\n                \"amqp channel '{alias}': invalid client certificate: {e}\"\n            ))\n        })?;\n","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/amqp.rs#L364-L400","documentation":"The configured client_cert file was read successfully but contained zero PEM CERTIFICATE sections — rustls_pemfile::certs found nothing to import while building the PKCS#12 client identity in pem_to_pkcs12_der. This is a file-content problem detected before any network connection is made.","triggerScenarios":"The client_cert path points at a file with no CERTIFICATE blocks: the private key file (cert and key paths swapped), a CSR, an empty file, or a DER-encoded binary certificate instead of PEM.","commonSituations":"Cert/key path swaps in config; provisioning scripts writing the wrong artifact; CAs or tooling that deliver DER by default; truncated files from a partial secret sync.","solutions":["Inspect the file for a BEGIN CERTIFICATE block: openssl x509 -in client.pem -noout","If cert and key were swapped, point client_cert at the certificate and client_key at the private key.","Convert DER to PEM if needed: openssl x509 -inform der -in cert.der -out client.pem"],"exampleFix":"# before: client_cert points at the private key file (no CERTIFICATE blocks)\nclient_cert = \"/etc/zeroclaw/tls/client.key\"\n\n# after\nclient_cert = \"/etc/zeroclaw/tls/client.pem\"  # leaf cert (+ chain) in PEM\nclient_key = \"/etc/zeroclaw/tls/client.key\"","handlingStrategy":"validation","validationCode":"fn pem_contains_certs(path: &std::path::Path) -> anyhow::Result<bool> {\n    let pem = std::fs::read(path)?;\n    let n = rustls_pemfile::certs(&mut &pem[..]).count();\n    Ok(n > 0)\n}","typeGuard":"fn looks_like_cert_pem(path: &std::path::Path) -> bool {\n    std::fs::read_to_string(path)\n        .map(|s| s.contains(\"BEGIN CERTIFICATE\"))\n        .unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Run openssl x509 -noout on every cert path during provisioning","Name files by role (client.crt vs client.key) to avoid swaps","Reject malformed PEMs at config load instead of failing at connect"],"tags":["rust","amqp","tls","pem","certificate","config-validation"],"backgroundTag":"invalid-pem-certificate","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}