{"record":{"id":"34cb32935cff13c8","repo":"EpicGames/lore","slug":"missing-cert-chain","errorCode":null,"errorMessage":"Missing cert chain","messagePattern":"Missing cert chain","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"lore-server/src/server.rs","lineNumber":379,"sourceCode":"    metrics_frequency: Duration,\n    quic_settings: QuicSettings,\n    generate_ephemeral_cert: bool,\n    mut shutdown_rx: tokio::sync::watch::Receiver<bool>,\n) -> Result<()> {\n    let span = info_span!(\"QUIC server\", name);\n\n    async {\n        let cert_settings = match quic_settings.certificate.clone() {\n            Some(cert_settings) => cert_settings,\n            None if generate_ephemeral_cert => generate_ephemeral_certificate(name)?,\n            None => return Err(anyhow!(\"Missing QUIC certificate config\")),\n        };\n\n        let client_verifier = if quic_settings.verify_client_certs {\n            let ca_path = cert_settings\n                .cert_chain\n                .clone()\n                .ok_or(anyhow!(\"Missing cert chain\"))?;\n            build_cert_verifier(ca_path)?\n        } else {\n            Arc::new(NoClientAuth {})\n        };\n\n        let addr = SocketAddr::from_str(\n            format!(\"{}:{}\", quic_settings.host, quic_settings.port).as_str(),\n        )?;\n\n        let mut settings_builder: QuinnConfigBuilder = quic_settings.into();\n\n        settings_builder = settings_builder\n            .server_metrics_name(name)\n            .address(addr)\n            .cert_chain(cert_settings.cert_chain)\n            .cert_file(cert_settings.cert_file)\n            .pkey_file(cert_settings.pkey_file)\n            .client_cert_verifier(client_verifier)","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-server/src/server.rs#L361-L397","documentation":"When the QUIC server is configured to verify client certificates (mTLS), a CA certificate chain file is required to build the client cert verifier. If cert_settings.cert_chain is None, startup fails with this error.","triggerScenarios":"quic_settings.verify_client_certs = true but the certificate settings lack a cert_chain (CA bundle) path; build_cert_verifier is never called.","commonSituations":"Enabling mTLS in config without adding the CA chain; operators setting verify_client_certs by default in hardened deployments but forgetting the CA file; copied config templates missing the field.","solutions":["Set cert_chain in the QUIC certificate settings to point at the CA bundle used to sign client certs","Disable verify_client_certs if client authentication is not actually required","Ensure the CA file exists and is readable at the configured path"],"exampleFix":"// before\n[quic.certificate]\ncert = \"/etc/certs/server.crt\"\nkey = \"/etc/certs/server.key\"\n// after\n[quic.certificate]\ncert = \"/etc/certs/server.crt\"\nkey = \"/etc/certs/server.key\"\ncert_chain = \"/etc/certs/ca-chain.crt\"","handlingStrategy":"validation","validationCode":"if quic_settings.verify_client_certs && quic_settings.certificate.as_ref().and_then(|c| c.cert_chain.as_ref()).is_none() {\n    return Err(\"verify_client_certs requires quic.certificate.cert_chain (CA bundle)\".into());\n}","typeGuard":"fn mtls_ready(c: &CertSettings) -> bool { c.cert_chain.is_some() }","tryCatchPattern":"match launch_quinn_server(&settings, false).await {\n    Err(e) if e.to_string().contains(\"Missing cert chain\") => eprintln!(\"set quic.certificate.cert_chain or disable verify_client_certs\"),\n    r => r?,\n}","preventionTips":["Treat verify_client_certs and cert_chain as an atomic pair in config validation","Verify the CA file exists and is readable during startup checks","Keep CA bundles in the same secret store as server certs"],"tags":["rust","quic","mtls","configuration"],"backgroundTag":"missing-required-config-field","analyzedSha":"074eb0b0d1194c997d7cf28b55519e3e197b3e23","analyzedAt":"2026-09-13T09:00:57.509Z","contentChangedAt":"2026-09-13T09:00:57.509Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}