{"record":{"id":"40b0d60b2fa8e8a7","repo":"hyperledger/fabric","slug":"chaincode-tls-cert-not-provided","errorCode":null,"errorMessage":"chaincode tls cert not provided","messagePattern":"chaincode tls cert not provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/container/externalbuilder/instance.go","lineNumber":98,"sourceCode":"\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)}\n\n\treturn connInfo, nil\n}","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/container/externalbuilder/instance.go#L80-L116","documentation":"With clientAuthRequired enabled, the peer must present a client certificate during the mutual-TLS handshake with the chaincode server; connection.json lacking `client_cert` makes the required credential unavailable.","triggerScenarios":"connection.json sets tls_required and client_auth_required true with a client_key present, but `client_cert` is empty in ChaincodeServerInfo.","commonSituations":"Partial TLS fields in connection.json; cert and key files swapped or only key copied; release script templating bug dropping the cert field.","solutions":["Set `client_cert` to the PEM-encoded client TLS certificate matching client_key","If client auth is unnecessary, set client_auth_required to false","Regenerate connection.json from the builder's release template including cert+key+root cert"],"exampleFix":"// before\n{\"client_auth_required\":true,\"client_key\":\"key.pem\"}\n// after\n{\"client_auth_required\":true,\"client_key\":\"key.pem\",\"client_cert\":\"cert.pem\"}","handlingStrategy":"validation","validationCode":"var ud ChaincodeServerUserData\njson.Unmarshal(connJSON, &ud)\nif ud.TLSRequired && ud.ClientAuthRequired && ud.ClientCert == \"\" {\n    return errors.New(\"client_cert PEM required for mutual TLS\")\n}\nblock, _ := pem.Decode([]byte(ud.ClientCert))\nif block == nil || block.Type != \"CERTIFICATE\" { return errors.New(\"client_cert is not a PEM certificate\") }","typeGuard":null,"tryCatchPattern":"info, err := ud.ChaincodeServerInfo(cryptoDir)\nif err != nil && strings.Contains(err.Error(), \"tls cert not provided\") {\n    return fmt.Errorf(\"provide client_cert in connection.json or disable client_auth_required: %w\", err)\n}","preventionTips":["Generate cert+key as a pair and emit both fields together","PEM-decode fields in CI to catch swapped/missing certs","Keep a connection.json template listing every required TLS field"],"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"}