{"record":{"id":"f49451948a7f79e8","repo":"hyperledger/fabric","slug":"must-set-either-peer-tls-key-file-and-peer-tls-ce","errorCode":null,"errorMessage":"must set either [peer.tls.key.file and peer.tls.cert.file] or [peer.tls.clientKey.file and peer.tls.clientCert.file]when peer.tls.clientAuthEnabled is set to true","messagePattern":"must set either \\[peer\\.tls\\.key\\.file and peer\\.tls\\.cert\\.file\\] or \\[peer\\.tls\\.clientKey\\.file and peer\\.tls\\.clientCert\\.file\\]when peer\\.tls\\.clientAuthEnabled is set to true","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/peer/config.go","lineNumber":489,"sourceCode":"\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)\n\tif err != nil {\n\t\treturn cert, errors.WithMessage(err,\n\t\t\t\"error loading client TLS certificate\")\n\t}\n\tcert, err = tls.X509KeyPair(clientCert, clientKey)\n\tif err != nil {","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/peer/config.go#L471-L507","documentation":"GetClientCertificate requires a TLS keypair when peer.tls.clientAuthEnabled is true. If neither the client pair (clientKey.file/clientCert.file) nor the server pair (key.file/cert.file) is configured at all, this error is returned telling the operator which combinations are acceptable.","triggerScenarios":"peer.tls.clientAuthEnabled=true while all four of peer.tls.clientKey.file, peer.tls.clientCert.file, peer.tls.key.file, peer.tls.cert.file are empty.","commonSituations":"Enabling CORE_PEER_TLS_CLIENTAUTH_ENABLED without providing any key files; inheriting a config from a TLS-disabled peer and flipping clientAuthEnabled on; misconfigured env prefix so viper sees nothing.","solutions":["Set peer.tls.clientKey.file and peer.tls.clientCert.file (preferred explicit client pair).","Alternatively ensure peer.tls.key.file and peer.tls.cert.file are both set.","Or disable clientAuthEnabled if mutual TLS is not required.","Verify env vars actually reach the process (CORE_PEER_TLS_* prefix correct, no env stripping)."],"exampleFix":"// before\ntls:\n  clientAuthEnabled: true\n  # no key/cert files configured\n// after\ntls:\n  clientAuthEnabled: true\n  clientKey.file: /etc/hyperledger/fabric/tls/client.key\n  clientCert.file: /etc/hyperledger/fabric/tls/client.crt","handlingStrategy":"validation","validationCode":"if viper.GetBool(\"peer.tls.clientAuthEnabled\") {\n  hasClientPair := viper.GetString(\"peer.tls.clientKey.file\") != \"\" && viper.GetString(\"peer.tls.clientCert.file\") != \"\"\n  hasServerPair := viper.GetString(\"peer.tls.key.file\") != \"\" && viper.GetString(\"peer.tls.cert.file\") != \"\"\n  if !hasClientPair && !hasServerPair {\n    return errors.New(\"clientAuthEnabled requires a complete key/cert pair\")\n  }\n}","typeGuard":null,"tryCatchPattern":"cert, err := GetClientCertificate()\nif err != nil && strings.Contains(err.Error(), \"clientAuthEnabled is set to true\") {\n  log.Fatalf(\"provide a TLS key/cert pair when client auth is enabled: %v\", err)\n}","preventionTips":["Enable clientAuthEnabled only alongside a provisioned keypair","Run a GetClientCertificate smoke test at startup","Keep all TLS env vars in one validated block"],"tags":["tls","config","mutual-tls","hyperledger-fabric"],"backgroundTag":"tls-client-auth-missing-keypair","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"}