hyperledger/fabric · error
access denied
Error message
access denied
What it means
The discovery service returns the sentinel accessDenied error for any query whose channel doesn't exist locally or whose client identity isn't eligible for discovery service on that channel (TLS/client cert checks in the auth filter). It is a deliberate opaque denial: the server logs the real reason but tells the client only 'access denied' so discovery doesn't leak channel information.
Source
Thrown at discovery/service.go:26
import (
"bytes"
"context"
"encoding/hex"
"fmt"
"github.com/hyperledger/fabric-lib-go/common/flogging"
"github.com/hyperledger/fabric-protos-go-apiv2/discovery"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/discovery/protoext"
common2 "github.com/hyperledger/fabric/gossip/common"
"github.com/hyperledger/fabric/protoutil"
"github.com/pkg/errors"
)
var logger = flogging.MustGetLogger("discovery")
var accessDenied = wrapError(errors.New("access denied"))
// certHashExtractor extracts the TLS certificate from a given context
// and returns its hash
type certHashExtractor func(ctx context.Context) []byte
// dispatcher defines a function that dispatches a query
type dispatcher func(q *discovery.Query) *discovery.QueryResult
type Service struct {
config Config
channelDispatchers map[protoext.QueryType]dispatcher
localDispatchers map[protoext.QueryType]dispatcher
auth *authCache
Support
}
// Config defines the configuration of the discovery service
type Config struct {View on GitHub (pinned to 2736b63f8f)
Solutions
- Check the peer's discovery log for the warning line ('doesn't exist' vs 'isn't eligible') to learn the real cause
- Verify the channel name and that the peer is joined to it (peer channel list)
- Configure discovery.authCacheEnabled/authenticator so the client's TLS cert is recognized, and send the correct client cert hash in the request
- Regenerate/rotate client TLS certificates and retry; ensure core.yaml discovery settings match your deployment
Example fix
// before client.Discover(ctx, channel="mychan") // peer not joined // after peer channel join --channelID mychannel client.Discover(ctx, channel="mychannel")
Defensive patterns
Strategy: try-catch
Validate before calling
channels, err := clientForPeer.DiscoverChannels(ctx)
if err != nil || !containsChannel(channels, targetChannel) {
return fmt.Errorf("peer not joined to %s", targetChannel)
} Try / catch
peers, err := client.PeersForEndorsement(ctx, req)
if err != nil && strings.Contains(err.Error(), "access denied") {
// check peer discovery logs for 'doesn't exist' vs 'isn't eligible';
// fix channel name or TLS client cert, then retry
} Prevention
- Verify channel names against peer channel list
- Keep discovery TLS client certificate configuration in sync with cert rotation
- Send channel-less queries only where the server's auth config permits them
When it happens
Trigger: processQuery receives a query with a Channel that s.ChannelExists doesn't know (client asking about a channel the peer isn't joined to), or s.auth.EligibleForService fails (client TLS cert not among discovery.authenticator clientCertRefs, wrong TLS material, or channel-less query when TLS disallows it).
Common situations: Typo'd or nonexistent channel name; peer not joined to the channel; client not presenting the expected TLS certificate (discovery.authTLSasCertHash / clientCertHashRef misconfig); using channel-less discovery queries when service requires a channel; stale TLS certs after rotation.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- client didn't send a TLS certificate
- client claimed TLS hash doesn't match computed TLS hash from
- channel %s doesn't exist
- failed obtaining channel application writers policy
- could not connect to ordering service
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/f4394953737c4cca.
Report an issue: GitHub.