{"record":{"id":"fb83da0b17d61228","repo":"hyperledger/fabric","slug":"peer-tls-key-file-and-peer-tls-cert-file-must-both","errorCode":null,"errorMessage":"peer.tls.key.file and peer.tls.cert.file must both be set or must both be empty","messagePattern":"peer\\.tls\\.key\\.file and peer\\.tls\\.cert\\.file must both be set or must both be empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/peer/config.go","lineNumber":483,"sourceCode":"\n\tif keyPath != \"\" || certPath != \"\" {\n\t\t// need both keyPath and certPath to be set\n\t\tif keyPath == \"\" || certPath == \"\" {\n\t\t\treturn cert, errors.New(\"peer.tls.clientKey.file and \" +\n\t\t\t\t\"peer.tls.clientCert.file must both be set or must both be empty\")\n\t\t}\n\t\tkeyPath = config.GetPath(\"peer.tls.clientKey.file\")\n\t\tcertPath = config.GetPath(\"peer.tls.clientCert.file\")\n\n\t} else {\n\t\t// use the TLS server keypair\n\t\tkeyPath = viper.GetString(\"peer.tls.key.file\")\n\t\tcertPath = viper.GetString(\"peer.tls.cert.file\")\n\n\t\tif keyPath != \"\" || certPath != \"\" {\n\t\t\t// need both keyPath and certPath to be set\n\t\t\tif keyPath == \"\" || certPath == \"\" {\n\t\t\t\treturn cert, errors.New(\"peer.tls.key.file and \" +\n\t\t\t\t\t\"peer.tls.cert.file must both be set or must both be empty\")\n\t\t\t}\n\t\t\tkeyPath = config.GetPath(\"peer.tls.key.file\")\n\t\t\tcertPath = config.GetPath(\"peer.tls.cert.file\")\n\t\t} else {\n\t\t\treturn cert, errors.New(\"must set either \" +\n\t\t\t\t\"[peer.tls.key.file and peer.tls.cert.file] or \" +\n\t\t\t\t\"[peer.tls.clientKey.file and peer.tls.clientCert.file]\" +\n\t\t\t\t\"when peer.tls.clientAuthEnabled is set to true\")\n\t\t}\n\t}\n\t// get the keypair from the file system\n\tclientKey, err := os.ReadFile(keyPath)\n\tif err != nil {\n\t\treturn cert, errors.WithMessage(err,\n\t\t\t\"error loading client TLS key\")\n\t}\n\tclientCert, err := os.ReadFile(certPath)","sourceCodeStart":465,"sourceCodeEnd":501,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/peer/config.go#L465-L501","documentation":"Within GetClientCertificate, when neither clientKey/clientCert is set, the code falls back to the server keypair paths peer.tls.key.file and peer.tls.cert.file (relevant when clientAuthEnabled). If exactly one of those two is set, the configuration is inconsistent and this error is returned.","triggerScenarios":"Calling GetClientCertificate with peer.tls.clientAuthEnabled=true, no clientKey/clientCert pair, and only one of peer.tls.key.file / peer.tls.cert.file configured.","commonSituations":"Setting CORE_PEER_TLS_KEY_FILE without CORE_PEER_TLS_CERT_FILE in the peer env; partially commented-out TLS block in core.yaml; automation that overwrites one of the two paths.","solutions":["Set both peer.tls.key.file and peer.tls.cert.file (CORE_PEER_TLS_KEY_FILE and CORE_PEER_TLS_CERT_FILE) to valid paths.","Or configure the explicit client pair peer.tls.clientKey.file and peer.tls.clientCert.file together.","If neither is intended, remove both keys — but note clientAuthEnabled=true requires one complete pair."],"exampleFix":"// before (core.yaml)\npeer:\n  tls:\n    key.file: /etc/hyperledger/fabric/tls/server.key\n    # cert.file missing\n// after\npeer:\n  tls:\n    key.file: /etc/hyperledger/fabric/tls/server.key\n    cert.file: /etc/hyperledger/fabric/tls/server.crt","handlingStrategy":"validation","validationCode":"keyPath := viper.GetString(\"peer.tls.key.file\")\ncertPath := viper.GetString(\"peer.tls.cert.file\")\nif (keyPath == \"\") != (certPath == \"\") {\n  return errors.New(\"server key and cert must both be set or both empty\")\n}","typeGuard":null,"tryCatchPattern":"cert, err := GetClientCertificate()\nif err != nil && strings.Contains(err.Error(), \"peer.tls.key.file and peer.tls.cert.file\") {\n  log.Fatalf(\"incomplete TLS key/cert pair: %v\", err)\n}","preventionTips":["Never partially comment the TLS config block","Emit key and cert env vars together from templates","CI-validate TLS config before deploy"],"tags":["tls","config","mutual-tls","hyperledger-fabric"],"backgroundTag":"tls-key-cert-pair-mismatch","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}