hyperledger/fabric · error
group %s isn't mapped to endorsers, but exists in a layout
Error message
group %s isn't mapped to endorsers, but exists in a layout
What it means
createEndorsementDescriptor validates that every group referenced in an endorsement descriptor's Layouts (QuantitiesByGroup) also appears in the descriptor's EndorsersByGroups map. When a layout requires a group the server never populated with endorsers, this error names the missing group. It indicates inconsistent endorsement descriptor data returned by the discovery server.
Source
Thrown at discovery/client/client.go:510
return err
}
resp[key] = descriptor
}
return nil
}
func (resp response) createEndorsementDescriptor(desc *discovery.EndorsementDescriptor, channel string) (*endorsementDescriptor, error) {
descriptor := &endorsementDescriptor{
layouts: []map[string]int{},
endorsersByGroups: make(map[string][]*Peer),
}
for _, l := range desc.Layouts {
currentLayout := make(map[string]int)
descriptor.layouts = append(descriptor.layouts, currentLayout)
for grp, count := range l.QuantitiesByGroup {
if _, exists := desc.EndorsersByGroups[grp]; !exists {
return nil, errors.Errorf("group %s isn't mapped to endorsers, but exists in a layout", grp)
}
currentLayout[grp] = int(count)
}
}
for grp, peers := range desc.EndorsersByGroups {
var endorsers []*Peer
for _, p := range peers.Peers {
peer, err := endorser(p, desc.Chaincode, channel)
if err != nil {
return nil, errors.Wrap(err, "failed creating endorser object")
}
endorsers = append(endorsers, peer)
}
descriptor.endorsersByGroups[grp] = endorsers
}
return descriptor, nilView on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure all organizations/groups in the endorsement policy have reachable peers that joined the channel
- Verify anchor peers are configured so gossip disseminates membership across orgs
- Check that the endorsement policy's required orgs actually have peers running the chaincode
- Retry after gossip converges (peers may still be joining)
- Inspect peer discovery logs to see why the group's endorsers list is empty
Defensive patterns
Strategy: retry
Validate before calling
// Pre-check: all orgs in the endorsement policy have live peers
for _, org := range policyOrgs(channel) {
if !hasLivePeerInOrg(channel, org) {
return fmt.Errorf("org %s has no live peers on channel %s", org, channel)
}
} Try / catch
desc, err := resolveEndorsers(ctx)
if err != nil && strings.Contains(err.Error(), "isn't mapped to endorsers") {
// org peers likely still joining; wait and retry
time.Sleep(5 * time.Second)
desc, err = resolveEndorsers(ctx)
} Prevention
- Configure anchor peers so all orgs gossip membership
- Add orgs' peers before enforcing policies requiring them
- Wait for gossip convergence after channel membership changes
- Monitor peer liveness per organization
When it happens
Trigger: Processing a discovery ChaincodeQueryResult whose EndorsementDescriptor has a layout quantity key with no matching entry in EndorsersByGroups — typically when the server has layout plans for peers/groups (e.g. by MSP or organization) but no live endorsers discovered for that group.
Common situations: An organization's peers are down or not gossiped yet so the server knows the layout but has no endorsers for the group; anchor peer misconfiguration breaking cross-org gossip; new org added to channel policy before its peers joined; stale discovery cache on the peer.
Related errors
- failed creating endorser object
- received empty envelope(s) for endorsers for chaincode %s, c
- message isn't an alive message
- membership is empty
- timestamp is nil
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/90de8ccad368e8b2.
Report an issue: GitHub.