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

  1. Populate req.Authentication.ClientIdentity with the client's serialized identity (e.g. x509 certificate bytes) before sending the discovery request
  2. Verify the client config/credential loading path actually returns the identity and is not silently empty
  3. Use a maintained SDK (e.g. fabric-sdk-go) that sets authentication automatically from the signing identity
  4. 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

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

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/c39b7f8e3bdb0d37. Report an issue: GitHub.