hyperledger/fabric · error

received bad response, status %d: %s

Error message

received bad response, status %d: %s

What it means

Returned by joinBySnapshotStatus when the endorser responded but with a non-200 status (or a nil Response). The proposal was processed by the peer, but the chaincode-level execution rejected it; the peer's status code and message are included in the error.

Source

Thrown at internal/peer/channel/joinbysnapshotstatus.go:93

	c, _ := cc.cf.Signer.Serialize()
	prop, _, err = protoutil.CreateProposalFromCIS(common2.HeaderType_ENDORSER_TRANSACTION, "", invocation, c)
	if err != nil {
		return nil, fmt.Errorf("cannot create proposal, due to %s", err)
	}

	var signedProp *pb.SignedProposal
	signedProp, err = protoutil.GetSignedProposal(prop, cc.cf.Signer)
	if err != nil {
		return nil, fmt.Errorf("cannot create signed proposal, due to %s", err)
	}

	proposalResp, err := cc.cf.EndorserClient.ProcessProposal(context.Background(), signedProp)
	if err != nil {
		return nil, fmt.Errorf("failed sending proposal, due to %s", err)
	}

	if proposalResp.Response == nil || proposalResp.Response.Status != http.StatusOK {
		return nil, fmt.Errorf("received bad response, status %d: %s", proposalResp.Response.Status, proposalResp.Response.Message)
	}

	joinbysnapshotStatus := &pb.JoinBySnapshotStatus{}
	err = proto.Unmarshal(proposalResp.Response.Payload, joinbysnapshotStatus)
	if err != nil {
		return nil, fmt.Errorf("cannot query joinbysnapshot status, due to %s", err)
	}
	return joinbysnapshotStatus, nil
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Read the status code and message embedded in the error for the peer-side reason
  2. Verify the channel exists on the peer and a snapshot/join-by-snapshot operation is actually in progress
  3. Ensure peer and CLI versions both support the joinbysnapshot feature (v3.x)
  4. Check peer logs at the time of the request for the underlying chaincode error

Example fix

// before: querying status when no join-by-snapshot in progress -> peer returns 500
peer channel joinbysnapshot status -c mychannel
// after: verify state first / handle non-200 explicitly
if resp.Response != nil && resp.Response.Status != http.StatusOK {
    log.Printf("peer rejected status query (%d): %s", resp.Response.Status, resp.Response.Message)
}
Defensive patterns

Strategy: type-guard

Type guard

func okEndorserResponse(resp *pb.ProposalResponse) bool {
    return resp != nil && resp.Response != nil && resp.Response.Status == http.StatusOK
}

Try / catch

if proposalResp.Response == nil || proposalResp.Response.Status != http.StatusOK {
    // branch on status: 500 -> peer/chaincode issue; 403 -> permissions; retry only transient codes
    return nil, fmt.Errorf("received bad response, status %d: %s", proposalResp.Response.Status, proposalResp.Response.Message)
}

Prevention

When it happens

Trigger: proposalResp.Response == nil or proposalResp.Response.Status != http.StatusOK — e.g. the peer returns 500 because the JoinBySnapshotStatus chaincode call failed internally, or 403/404 style errors from endorsement policy/unknown channel.

Common situations: The peer does not have the channel/snapshot context the command expects; chaincode handler on the peer errors out (snapshot metadata missing or join not in progress); client lacks permission to query; peer version doesn't support joinbysnapshot (feature not enabled).

Related errors


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