{"record":{"id":"fa46fe65ceaf8e9f","repo":"hyperledger/fabric","slug":"chaincode-tls-key-not-provided","errorCode":null,"errorMessage":"chaincode tls key not provided","messagePattern":"chaincode tls key not provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/container/externalbuilder/instance.go","lineNumber":95,"sourceCode":"func (c *ChaincodeServerUserData) ChaincodeServerInfo(cryptoDir string) (*ccintf.ChaincodeServerInfo, error) {\n\tif c.Address == \"\" {\n\t\treturn nil, errors.New(\"chaincode address not provided\")\n\t}\n\tconnInfo := &ccintf.ChaincodeServerInfo{Address: c.Address}\n\n\tconnInfo.ClientConfig.DialTimeout = time.Duration(c.DialTimeout)\n\tif connInfo.ClientConfig.DialTimeout == 0 {\n\t\tconnInfo.ClientConfig.DialTimeout = DialTimeout\n\t}\n\n\t// we can expose this if necessary\n\tconnInfo.ClientConfig.KaOpts = comm.DefaultKeepaliveOptions\n\n\tif !c.TLSRequired {\n\t\treturn connInfo, nil\n\t}\n\tif c.ClientAuthRequired && c.ClientKey == \"\" {\n\t\treturn nil, errors.New(\"chaincode tls key not provided\")\n\t}\n\tif c.ClientAuthRequired && c.ClientCert == \"\" {\n\t\treturn nil, errors.New(\"chaincode tls cert not provided\")\n\t}\n\tif c.RootCert == \"\" {\n\t\treturn nil, errors.New(\"chaincode tls root cert not provided\")\n\t}\n\n\tconnInfo.ClientConfig.SecOpts.UseTLS = true\n\n\tif c.ClientAuthRequired {\n\t\tconnInfo.ClientConfig.SecOpts.RequireClientCert = true\n\t\tconnInfo.ClientConfig.SecOpts.Certificate = []byte(c.ClientCert)\n\t\tconnInfo.ClientConfig.SecOpts.Key = []byte(c.ClientKey)\n\t\tconnInfo.ClientConfig.SecOpts.ServerNameOverride = c.Domain\n\t}\n\n\tconnInfo.ClientConfig.SecOpts.ServerRootCAs = [][]byte{[]byte(c.RootCert)}","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/container/externalbuilder/instance.go#L77-L113","documentation":"When TLS is required and client authentication (mutual TLS) is also required, the peer needs the chaincode's client TLS private key to present in the handshake; connection.json without `client_key` cannot form a mutual-TLS dial.","triggerScenarios":"connection.json has tls_required and client_auth_required true, but `client_key` is empty when ChaincodeServerInfo assembles the client SecOpts.","commonSituations":"Release step emitted certs but not the key; key mounted but path/env not passed into connection.json; user intentionally omitted private key for security but enabled client auth.","solutions":["Set `client_key` in connection.json to the PEM-encoded client TLS private key","If mutual TLS is not needed, set client_auth_required to false","Ensure the release script/template includes all four TLS fields (client_key, client_cert, root_cert, address)"],"exampleFix":"// before\n{\"tls_required\":true,\"client_auth_required\":true,\"client_cert\":\"cert.pem\"}\n// after\n{\"tls_required\":true,\"client_auth_required\":true,\"client_cert\":\"cert.pem\",\"client_key\":\"key.pem\",\"root_cert\":\"root.pem\"}","handlingStrategy":"validation","validationCode":"var ud ChaincodeServerUserData\njson.Unmarshal(connJSON, &ud)\nif ud.TLSRequired && ud.ClientAuthRequired && ud.ClientKey == \"\" {\n    return errors.New(\"client_key PEM required for mutual TLS\")\n}","typeGuard":null,"tryCatchPattern":"info, err := ud.ChaincodeServerInfo(cryptoDir)\nif err != nil && strings.Contains(err.Error(), \"tls key not provided\") {\n    return fmt.Errorf(\"provide client_key in connection.json or disable client_auth_required: %w\", err)\n}","preventionTips":["Emit client_key, client_cert, and root_cert together when client_auth_required is true","Never enable client_auth_required without distributing the client key","Validate connection.json TLS fields before launching the chaincode"],"tags":["tls","mutual-tls","chaincode-as-a-service","missing-field"],"backgroundTag":"missing-tls-credential","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"}