hyperledger/fabric · error
access denied, client identity wasn't supplied
Error message
access denied, client identity wasn't supplied
What it means
This error is returned by the discovery service's validateStructure when a client submits a discovery request whose Authentication section either has an empty ClientIdentity field or no Authentication at all is impossible — here specifically the Authentication object exists but ClientIdentity is empty. The discovery service requires the caller to identify itself so the server can authorize the request.
Source
Thrown at discovery/service.go:245
}
}
return peersByOrg
}
// validateStructure validates that the request contains all the needed fields and that they are computed correctly
func validateStructure(ctx context.Context, request *discovery.SignedRequest, tlsEnabled bool, certHashFromContext certHashExtractor) (*discovery.Request, error) {
if request == nil {
return nil, errors.New("nil request")
}
req, err := protoext.SignedRequestToRequest(request)
if err != nil {
return nil, errors.Wrap(err, "failed parsing request")
}
if req.Authentication == nil {
return nil, errors.New("access denied, no authentication info in request")
}
if len(req.Authentication.ClientIdentity) == 0 {
return nil, errors.New("access denied, client identity wasn't supplied")
}
if !tlsEnabled {
return req, nil
}
computedHash := certHashFromContext(ctx)
if len(computedHash) == 0 {
return nil, errors.New("client didn't send a TLS certificate")
}
if !bytes.Equal(computedHash, req.Authentication.ClientTlsCertHash) {
claimed := hex.EncodeToString(req.Authentication.ClientTlsCertHash)
logger.Warningf("client claimed TLS hash %s doesn't match computed TLS hash from gRPC stream %s", claimed, hex.EncodeToString(computedHash))
return nil, errors.New("client claimed TLS hash doesn't match computed TLS hash from gRPC stream")
}
return req, nil
}
func validateCCQuery(ccQuery *discovery.ChaincodeQuery) error {
if len(ccQuery.Interests) == 0 {View on GitHub (pinned to 2736b63f8f)
Solutions
- Populate req.Authentication.ClientIdentity with the client's serialized identity (e.g. x509 certificate bytes) before sending the discovery request
- Verify the client config/credential loading path actually returns the identity and is not silently empty
- Use a maintained SDK (e.g. fabric-sdk-go) that sets authentication automatically from the signing identity
- Test locally with TestValidateStructure to confirm the request passes structural validation before connecting
Example fix
// before
req := &discovery.Request{Authentication: &discovery.AuthInfo{}}
// after
req := &discovery.Request{Authentication: &discovery.AuthInfo{ClientIdentity: serializedIdentity}} Defensive patterns
Strategy: validation
Validate before calling
func validateAuth(req *discovery.Request) error {
if req.Authentication == nil || len(req.Authentication.ClientIdentity) == 0 {
return errors.New("discovery request requires a non-empty ClientIdentity")
}
return nil
} Type guard
func hasClientIdentity(req *discovery.Request) bool {
return req != nil && req.Authentication != nil && len(req.Authentication.ClientIdentity) > 0
} Try / catch
resp, err := client.Send(ctx, req)
if err != nil {
if strings.Contains(err.Error(), "client identity wasn't supplied") {
return fmt.Errorf("populating ClientIdentity and retrying: %w", reloadIdentityAndSend())
}
return err
} Prevention
- Always derive the AuthInfo from a loaded signing identity, never hand-build an empty Authentication
- Log identity length at client startup to confirm credentials loaded
- Validate the request with TestValidateStructure before sending in tests
When it happens
Trigger: Calling the Discover or TestValidateStructure RPC with a request where req.Authentication is non-nil but req.Authentication.ClientIdentity is an empty byte slice.
Common situations: Client SDK misconfiguration where the identity/credential material (e.g. an enrollment certificate or serialized identity) failed to load silently; constructing a discovery.Request by hand without populating Auth; upgrading an SDK and losing the identity config field.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- unknown or missing request type
- client didn't send a TLS certificate
- client claimed TLS hash doesn't match computed TLS hash from
- chaincode query must have at least one chaincode interest
- chaincode interest is nil
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/c39b7f8e3bdb0d37.
Report an issue: GitHub.