{"record":{"id":"664383db714d83c1","repo":"EpicGames/lore","slug":"tls-is-partially-configured-cert-file-and-pkey-file-must","errorCode":null,"errorMessage":"TLS is partially configured: cert_file and pkey_file must both be set or both be absent","messagePattern":"TLS is partially configured: cert_file and pkey_file must both be set or both be absent","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"lore-server/src/grpc/server.rs","lineNumber":459,"sourceCode":"    hook_dispatcher: Arc<HookDispatcher>,\n}\n\nimpl GrpcServerBuilder<WantsTlsConfig> {\n    pub fn with_tls_config(\n        self,\n        cert_path: Option<PathBuf>,\n        key_path: Option<PathBuf>,\n        cert_chain_path: Option<PathBuf>,\n    ) -> Result<GrpcServerBuilder<WantsAdminEndpoints>> {\n        let tls_config = match (cert_path, key_path) {\n            (Some(cert_path), Some(key_path)) => Some(build_server_tls_config(\n                cert_path,\n                key_path,\n                cert_chain_path,\n            )?),\n            (None, None) => None,\n            _ => {\n                return Err(anyhow!(\n                    \"TLS is partially configured: cert_file and pkey_file must both be set or both be absent\"\n                ));\n            }\n        };\n\n        Ok(GrpcServerBuilder(WantsAdminEndpoints {\n            environment: self.0.environment,\n            feature: self.0.feature,\n            immutable_store: self.0.immutable_store,\n            local_store: self.0.local_store,\n            mutable_store: self.0.mutable_store,\n            lock_store: self.0.lock_store,\n            hook_dispatcher: self.0.hook_dispatcher,\n            notification_sender: self.0.notification_sender,\n            notification_service: self.0.notification_service,\n            tls_config,\n        }))\n    }","sourceCodeStart":441,"sourceCodeEnd":477,"githubUrl":"https://github.com/EpicGames/lore/blob/074eb0b0d1194c997d7cf28b55519e3e197b3e23/lore-server/src/grpc/server.rs#L441-L477","documentation":"GrpcServerBuilder's TLS setup for the public gRPC server requires cert_file and pkey_file to be set together or not at all; any other combination (only cert, only key, or a chain without both) returns this error. A half-configured TLS server could not terminate TLS correctly.","triggerScenarios":"Configuring grpc.tls with cert_file set but pkey_file absent, or vice versa, when constructing the GrpcServer via its builder.","commonSituations":"Config templates where the key path was intentionally commented out for plaintext mode but the cert remained; secret injection failing for one of the two files; typo in one key so only the other is read.","solutions":["Set both cert_file and pkey_file, or remove both to run plaintext gRPC.","Verify both files exist and the config keys are spelled correctly.","If TLS is desired but the chain is the only extra item, still ensure cert+key are both present alongside it."],"exampleFix":"// before (config)\n[grpc.tls]\ncert_file = \"/certs/grpc.pem\"\n// pkey_file missing\n// after\n[grpc.tls]\ncert_file = \"/certs/grpc.pem\"\npkey_file = \"/certs/grpc.key\"","handlingStrategy":"validation","validationCode":"match (tls.cert_file.as_deref(), tls.pkey_file.as_deref()) {\n    (Some(_), Some(_)) | (None, None) => Ok(()),\n    _ => Err(\"grpc TLS needs both cert_file and pkey_file or neither\".into()),\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = build_grpc_server(...) {\n    if e.to_string().contains(\"TLS is partially configured\") {\n        eprintln!(\"set both grpc cert_file and pkey_file, or remove both\");\n    }\n    return Err(e);\n}","preventionTips":["Group cert+key in a single config section toggled by one enable flag.","Verify both files exist at startup with a filesystem pre-check.","When disabling TLS, comment out both keys together and diff configs before deploy."],"tags":["grpc","tls","config","startup"],"backgroundTag":"conflicting-config-options","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"}