hyperledger/fabric · error

server returned response of unexpected type: %v

Error message

server returned response of unexpected type: %v

What it means

ParseResponse expects Results[0] to be a chaincode query result (GetCcQueryRes). If that field is nil — the server returned some other QueryResult type (config, membership, or nil) — the parser rejects it with "server returned response of unexpected type". This is a type-mismatch guard ensuring the response matches the endorsers query that was sent.

Source

Thrown at discovery/cmd/endorsers.go:136

// EndorserResponseParser parses endorsement responses from the peer
type EndorserResponseParser struct {
	io.Writer
}

// ParseResponse parses the given response for the given channel
func (parser *EndorserResponseParser) ParseResponse(channel string, res ServiceResponse) error {
	rawResponse := res.Raw()
	if len(rawResponse.Results) == 0 {
		return errors.New("empty results")
	}

	if e := rawResponse.Results[0].GetError(); e != nil {
		return errors.Errorf("server returned: %s", e.Content)
	}

	ccQueryRes := rawResponse.Results[0].GetCcQueryRes()
	if ccQueryRes == nil {
		return errors.Errorf("server returned response of unexpected type: %v", reflect.TypeFor[*discovery.QueryResult]())
	}

	jsonBytes, _ := json.MarshalIndent(parseEndorsementDescriptors(ccQueryRes.Content), "", "\t")
	fmt.Fprintln(parser.Writer, string(jsonBytes))
	return nil
}

type chaincodesAndCollections struct {
	Chaincodes  *[]string
	Collections *map[string]string
	NoPrivReads *[]string
}

func (ec *chaincodesAndCollections) noPrivateReads(chaincodeName string) bool {
	return slices.Contains(*ec.NoPrivReads, chaincodeName)
}

func (ec *chaincodesAndCollections) existsInChaincodes(chaincodeName string) bool {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure ParseResponse is called on the response of an AddEndorsersQuery request, not a config/membership query
  2. Align peer and discovery client/CLI versions
  3. Inspect the raw response (res.Raw()) to see what result type was actually returned

Example fix

// before
res, _ := stub.Send(server, conf, configReq)
parser.ParseResponse(channel, res) // config response parsed as endorsers
// after
res, _ := stub.Send(server, conf, endorsersReq)
parser.ParseResponse(channel, res)
Defensive patterns

Strategy: type-guard

Validate before calling

raw := res.Raw()
if len(raw.Results) > 0 && raw.Results[0].GetCcQueryRes() == nil {
    return errors.New("response is not a chaincode query result; was this response from an endorsers query?")
}

Type guard

func isEndorsersResponse(res discovery.ServiceResponse) bool {
    raw := res.Raw()
    return len(raw.Results) > 0 && raw.Results[0].GetCcQueryRes() != nil
}

Try / catch

if err := parser.ParseResponse(channel, res); err != nil {
    if strings.Contains(err.Error(), "unexpected type") {
        return fmt.Errorf("response/query mismatch: ensure ParseResponse is paired with AddEndorsersQuery: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Sending an endorsers request but receiving a response whose first result is a config query result, membership result, or an unset/nil result — usually from mismatched request/response pairing or a server/client version mismatch.

Common situations: Reusing a response object from a different query type (config/membership) with the endorsers parser; peer version returning a different result schema; mixing discovery client versions between CLI and peer.

Related errors


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