EpicGames/lore · error · anyhow::Error
gRPC internal TLS is partially configured: cert=
Error message
gRPC internal TLS is partially configured: cert={}, key={}, cert_chain={}. Provide all three or none What it means
GrpcInternalServer::with_tls_config validates that gRPC internal TLS is configured all-or-nothing: server cert, private key, and client CA cert chain. If exactly one or two of the three are set, it returns this error listing which ones are present. Partial TLS would produce a server that cannot authenticate peers correctly.
Solutions
- Provide all three files (server cert, private key, client CA cert chain) in the internal TLS config, or remove all three.
- Check secret mounts/volumes so that all three files actually exist at the configured paths.
- Compare the config keys against the current struct fields after upgrades to catch renamed/missing entries.
Example fix
// before (config) [grpc_internal.tls] cert_file = "/certs/server.pem" pkey_file = "/certs/server.key" // cert_chain missing -> partial // after [grpc_internal.tls] cert_file = "/certs/server.pem" pkey_file = "/certs/server.key" cert_chain_file = "/certs/client-ca.pem"
Defensive patterns
Strategy: validation
Validate before calling
let parts = (tls.cert.as_deref(), tls.key.as_deref(), tls.chain.as_deref());
let set = parts.iter().filter(|p| p.is_some()).count();
if set != 0 && set != 3 {
return Err("internal gRPC TLS needs all of cert, key, cert_chain or none".into());
} Try / catch
if let Err(e) = GrpcInternalServer::with_tls_config(...) {
if e.to_string().contains("partially configured") {
eprintln!("fix internal TLS: provide cert, key AND cert_chain, or none");
}
return Err(e);
} Prevention
- Keep the three TLS files in one secret and mount them atomically.
- Templated configs: emit all-or-none blocks, not independently optional keys.
- Add a config linter that checks TLS field presence as a group.
When it happens
Trigger: Calling with_tls_config where internal_tls settings provide cert/key/cert_chain in a partial combination, e.g. only cert and key without cert_chain, or only cert_chain.
Common situations: Operators configure mTLS but forget the client CA chain; a secret-mount only partially populated so one file is missing and treated as unset; config templates that omit optional fields independently; upgrade changed field names so one key no longer maps.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- TLS is partially configured: cert_file and pkey_file must…
- Maintenance TLS is partially configured: cert_file and…
- certificate is partially configured: certificate.cert_file…
- requires mTLS to start (verify_client_certs = true)…
- presigned_url_hmac_key is not valid hex
AI-assisted analysis of EpicGames/lore@074eb0b0d1 (2026-09-13).
Data as JSON: /api/errors/69c8868fbe351918.
Report an issue: GitHub.
Appendix: source
Thrown at lore-server/src/grpc/grpc_internal_server.rs:140
) -> anyhow::Result<GrpcInternalServerBuilder<WantsHttp2Config>> {
let tls_config = match (cert_path, key_path, cert_chain_path) {
(Some(cert_path), Some(key_path), Some(cert_chain_path)) => {
info!("Loading TLS certs - cert: {cert_path:?} key: {key_path:?}");
let identity =
Identity::from_pem(std::fs::read(cert_path)?, std::fs::read(key_path)?);
info!("Using CA cert: {cert_chain_path:?}");
let ca_cert = std::fs::read(cert_chain_path)?;
Some(
ServerTlsConfig::new()
.identity(identity)
.client_ca_root(Certificate::from_pem(ca_cert)),
)
}
(None, None, None) => None,
(cert, key, chain) => {
return Err(anyhow!(
"gRPC internal TLS is partially configured: cert={}, key={}, cert_chain={}. \
Provide all three or none",
cert.is_some(),
key.is_some(),
chain.is_some(),
));
}
};
Ok(GrpcInternalServerBuilder(WantsHttp2Config {
local_immutable_store: self.0.local_immutable_store,
immutable_store: self.0.immutable_store,
mutable_store: self.0.mutable_store,
notification_sender: self.0.notification_sender,
hook_dispatcher: self.0.hook_dispatcher,
environment: self.0.environment,
tls_config,
}))View on GitHub (pinned to 074eb0b0d1)