hyperledger/fabric · error
error bad proposal response %d: %s
Error message
error bad proposal response %d: %s
What it means
The endorser did return a proposal response, but its embedded response status is neither 0 (unset) nor 200 OK. The error surfaces the peer's status code and message so the caller can see why the endorsement (GetChannelConfig) was rejected.
Source
Thrown at internal/peer/common/common.go:266
return nil, errors.WithMessage(err, "error creating GetChannelConfig proposal")
}
signedProp, err := protoutil.GetSignedProposal(prop, signer)
if err != nil {
return nil, errors.WithMessage(err, "error creating signed GetChannelConfig proposal")
}
proposalResp, err := endorserClient.ProcessProposal(context.Background(), signedProp)
if err != nil {
return nil, errors.WithMessage(err, "error endorsing GetChannelConfig")
}
if proposalResp == nil {
return nil, errors.New("received nil proposal response")
}
if proposalResp.Response.Status != 0 && proposalResp.Response.Status != http.StatusOK {
return nil, errors.Errorf("error bad proposal response %d: %s", proposalResp.Response.Status, proposalResp.Response.Message)
}
// parse config
channelConfig := &pcommon.Config{}
if err := proto.Unmarshal(proposalResp.Response.Payload, channelConfig); err != nil {
return nil, errors.WithMessage(err, "error unmarshalling channel config")
}
bundle, err := channelconfig.NewBundle(chainID, channelConfig, cryptoProvider)
if err != nil {
return nil, errors.WithMessage(err, "error loading channel config")
}
ordererConfig, ok := bundle.OrdererConfig()
if !ok {
return nil, errors.New("missing OrdererConfig in channel config")
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Read the %s message and %d status embedded in the error to identify the peer-side cause
- Verify the peer has joined the target channel (peer channel list)
- Check the client MSP identity has read access to channel config resources
- Retry with a different peer joined to the channel
Example fix
// before
resp, _ := common.GetOrdererEndpointOfChain("mychannel", nil, signer, certPool)
// after
resp, err := common.GetOrdererEndpointOfChain("mychannel", nil, signer, certPool)
if err != nil { log.Fatalf("endorsement rejected: %v", err) } Defensive patterns
Strategy: try-catch
Validate before calling
// verify peer has joined the channel before querying config // peer channel list | grep <channelID> // ensure the signer's MSP is enrolled and known to the peer
Type guard
if resp != nil && resp.Response != nil && (resp.Response.Status == 0 || resp.Response.Status == 200) {
// response is usable
} Try / catch
orderers, err := GetOrdererEndpointOfChain(chainID, dc, signer, cp)
if err != nil {
var statusErr interface{ Status() int32 }
log.Printf("endorsement rejected: %v", err) // status+message are embedded in the text
return err
} Prevention
- Confirm the peer has joined the target channel before querying
- Check ACL/policy grants for the client identity
- Read the embedded status code and message to triage quickly
When it happens
Trigger: endorserClient.ProcessProposal succeeds but proposalResp.Response.Status is a non-200 code, e.g. 500 (chained execution failure), 403/404 (access or unknown channel), 400 (bad proposal).
Common situations: Querying a channel the peer is not joined to (unknown channel), permission/ACL rejection for the requesting identity, chaincode/endorser internal error while loading channel config.
Related errors
- empty header extension
- no endorser clients retrieved - this might indicate a bug
- no proposal responses received - this might indicate a bug
- failed sending proposal, due to %s
- received bad response, status %d: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/c01557f5261f0f76.
Report an issue: GitHub.