{"record":{"id":"e984b0f7a6f94ccd","repo":"hyperledger/fabric","slug":"expected-queryresult-of-either-chaincodequeryresul","errorCode":null,"errorMessage":"expected QueryResult of either ChaincodeQueryResult or Error but got %v instead","messagePattern":"expected QueryResult of either ChaincodeQueryResult or Error but got (.+?) instead","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/client/client.go","lineNumber":456,"sourceCode":"\t\t\t})\n\t\t}\n\t}\n\treturn peers, nil\n}\n\nfunc isStateInfoExpected(qt protoext.QueryType) bool {\n\treturn qt != protoext.LocalMembershipQueryType\n}\n\nfunc (resp response) mapEndorsers(\n\tchannel2index map[string]int,\n\tr *discovery.Response,\n\tchaincodeQueryMapping map[int][]InvocationChain,\n) error {\n\tfor ch, index := range channel2index {\n\t\tccQueryRes, err := protoext.ResponseEndorsersAt(r, index)\n\t\tif ccQueryRes == nil && err == nil {\n\t\t\treturn errors.Errorf(\"expected QueryResult of either ChaincodeQueryResult or Error but got %v instead\", r.Results[index])\n\t\t}\n\n\t\tif err != nil {\n\t\t\tkey := key{\n\t\t\t\tqueryType: protoext.ChaincodeQueryType,\n\t\t\t\tk:         ch,\n\t\t\t}\n\t\t\tresp[key] = errors.New(err.Content)\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := resp.mapEndorsersOfChannel(ccQueryRes, ch, chaincodeQueryMapping[index]); err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed assembling endorsers of channel %s\", ch)\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/client/client.go#L438-L474","documentation":"When mapping endorsement results back to invocation chains, the client expects each channel-query result at Results[index] to be either a ChaincodeQueryResult or an Error (via ResponseEndorsersAt). If both the parsed result and error are nil, the result slot holds some other QueryResult type (e.g. Config or Membership) where a chaincode result was expected.","triggerScenarios":"Building a discovery request where queries were appended in an order that misaligns channel-to-index mapping, or the server returned a ConfigQueryResult/MembershipQueryResult at the index expected to be a chaincode/endorsement result.","commonSituations":"SDK users mixing query types in one request and reading results by wrong index; server-side behavior changes after Fabric upgrades; bugs in custom request construction (AddChaincodeQuery vs AddConfigQuery ordering).","solutions":["Ensure each AddChaincodeQuery/AddEndorsementQuery is matched with the correct channel and you index results in the same order queries were added.","Check that the peer's discovery service actually supports endorsement queries (some versions/configs reject or substitute results).","Inspect r.Results[index] content via logging to see what type was actually returned.","Upgrade client and peer to matched Fabric versions.","Rebuild the request adding queries per channel consistently."],"exampleFix":"// before: wrong result indexing after mixing query types\nreq.AddConfigQuery()\nreq.AddChaincodeQuery()\nres, _ := client.SendRequest(ctx, req)\nerr := mapEndorsers(res, chaincodeMapping) // hits config result at chaincode index\n// after: use ForChannel scopes and read results per query type in order\ncreq := discovery.NewQuery().ForChannel(ch)\ncreq.AddChaincodeQuery()\ncres, _ := client.SendRequest(ctx, creq)\n_ = mapEndorsers(cres, chaincodeMapping)","handlingStrategy":"type-guard","validationCode":"func resultAt(r *discovery.Response, i int) protoext.QueryResult {\n  if r == nil || i >= len(r.Results) { return nil }\n  return r.Results[i]\n}\n// before mapEndorsers, assert the slot is a chaincode/endorsement result","typeGuard":"func isChaincodeQueryResult(qr protoext.QueryResult) bool {\n  _, ok := qr.(*discovery.ChaincodeQueryResult)\n  return ok\n}","tryCatchPattern":"err := mapEndorsers(res, mapping)\nif err != nil && strings.Contains(err.Error(), \"expected QueryResult of either ChaincodeQueryResult or Error\") {\n  log.Printf(\"unexpected discovery result type at chaincode index; rebuilding request: %v\", err)\n  return rebuildAndSendRequest(ctx)\n}","preventionTips":["Add queries per channel and read results in the exact order added","Never mix config/chaincode queries in one request without tracking indices","Log raw r.Results when debugging discovery","Confirm endorsement query support on the target peer version"],"tags":["fabric","discovery","endorsement","query-result","type-mismatch"],"backgroundTag":"unexpected-response-type","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}