hyperledger/fabric · error

expected QueryResult of either ChaincodeQueryResult or Error

Error message

expected QueryResult of either ChaincodeQueryResult or Error but got %v instead

What it means

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.

Source

Thrown at discovery/client/client.go:456

			})
		}
	}
	return peers, nil
}

func isStateInfoExpected(qt protoext.QueryType) bool {
	return qt != protoext.LocalMembershipQueryType
}

func (resp response) mapEndorsers(
	channel2index map[string]int,
	r *discovery.Response,
	chaincodeQueryMapping map[int][]InvocationChain,
) error {
	for ch, index := range channel2index {
		ccQueryRes, err := protoext.ResponseEndorsersAt(r, index)
		if ccQueryRes == nil && err == nil {
			return errors.Errorf("expected QueryResult of either ChaincodeQueryResult or Error but got %v instead", r.Results[index])
		}

		if err != nil {
			key := key{
				queryType: protoext.ChaincodeQueryType,
				k:         ch,
			}
			resp[key] = errors.New(err.Content)
			continue
		}

		if err := resp.mapEndorsersOfChannel(ccQueryRes, ch, chaincodeQueryMapping[index]); err != nil {
			return errors.Wrapf(err, "failed assembling endorsers of channel %s", ch)
		}
	}
	return nil
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure each AddChaincodeQuery/AddEndorsementQuery is matched with the correct channel and you index results in the same order queries were added.
  2. Check that the peer's discovery service actually supports endorsement queries (some versions/configs reject or substitute results).
  3. Inspect r.Results[index] content via logging to see what type was actually returned.
  4. Upgrade client and peer to matched Fabric versions.
  5. Rebuild the request adding queries per channel consistently.

Example fix

// before: wrong result indexing after mixing query types
req.AddConfigQuery()
req.AddChaincodeQuery()
res, _ := client.SendRequest(ctx, req)
err := mapEndorsers(res, chaincodeMapping) // hits config result at chaincode index
// after: use ForChannel scopes and read results per query type in order
creq := discovery.NewQuery().ForChannel(ch)
creq.AddChaincodeQuery()
cres, _ := client.SendRequest(ctx, creq)
_ = mapEndorsers(cres, chaincodeMapping)
Defensive patterns

Strategy: type-guard

Validate before calling

func resultAt(r *discovery.Response, i int) protoext.QueryResult {
  if r == nil || i >= len(r.Results) { return nil }
  return r.Results[i]
}
// before mapEndorsers, assert the slot is a chaincode/endorsement result

Type guard

func isChaincodeQueryResult(qr protoext.QueryResult) bool {
  _, ok := qr.(*discovery.ChaincodeQueryResult)
  return ok
}

Try / catch

err := mapEndorsers(res, mapping)
if err != nil && strings.Contains(err.Error(), "expected QueryResult of either ChaincodeQueryResult or Error") {
  log.Printf("unexpected discovery result type at chaincode index; rebuilding request: %v", err)
  return rebuildAndSendRequest(ctx)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


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