{"record":{"id":"db0a495c4b6deb36","repo":"hyperledger/fabric","slug":"query-iterator-not-found","errorCode":null,"errorMessage":"query iterator not found","messagePattern":"query iterator not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/handler.go","lineNumber":900,"sourceCode":"\t\ttxContext.CleanupQueryContext(iterID)\n\t\treturn nil, errors.Wrap(err, \"marshal failed\")\n\t}\n\n\tchaincodeLogger.Debugf(\"Got keys and values. Sending %s\", pb.ChaincodeMessage_RESPONSE)\n\treturn &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil\n}\n\n// Handles query to ledger for query state next\nfunc (h *Handler) HandleQueryStateNext(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) {\n\tqueryStateNext := &pb.QueryStateNext{}\n\terr := proto.Unmarshal(msg.Payload, queryStateNext)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"unmarshal failed\")\n\t}\n\n\tqueryIter := txContext.GetQueryIterator(queryStateNext.Id)\n\tif queryIter == nil {\n\t\treturn nil, errors.New(\"query iterator not found\")\n\t}\n\n\ttotalReturnLimit := h.calculateTotalReturnLimit(nil)\n\n\tpayload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, queryIter, queryStateNext.Id, false, totalReturnLimit)\n\tif err != nil {\n\t\ttxContext.CleanupQueryContext(queryStateNext.Id)\n\t\treturn nil, errors.WithStack(err)\n\t}\n\tif payload == nil {\n\t\ttxContext.CleanupQueryContext(queryStateNext.Id)\n\t\treturn nil, errors.New(\"marshal failed: proto: Marshal called with nil\")\n\t}\n\n\tpayloadBytes, err := proto.Marshal(payload)\n\tif err != nil {\n\t\ttxContext.CleanupQueryContext(queryStateNext.Id)\n\t\treturn nil, errors.Wrap(err, \"marshal failed\")","sourceCodeStart":882,"sourceCodeEnd":918,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/handler.go#L882-L918","documentation":"Raised in HandleQueryStateNext when txContext.GetQueryIterator(id) returns nil, meaning no query iterator is registered in the transaction context under the given iterator ID. The handler cannot continue an iteration that was never created or has already been cleaned up.","triggerScenarios":"The chaincode sends a QueryStateNext message with an iterator ID that does not exist in txContext — typically after the iterator's TTL elapsed, after the query context was cleaned up, or when the ID was never created by a prior GetQueryResult/QueryStateNext response.","commonSituations":"Chaincode holds a state-query iterator across a long transaction while the peer's iterator TTL expires; calling Next after Close; parallel transactions reusing iterator IDs incorrectly; peer restart clearing in-memory iterator state.","solutions":["Complete iterator consumption (Next/Close) within a short window, well inside the peer's queryIterator TTL.","Never call Next after Close; check for closed iterators in chaincode code.","Reduce long-running transactions or increase iterator TTL (ledger state query limit settings) on the peer.","If the ID is genuinely stale, treat as a lifecycle bug: recreate the original query (GetQueryResult) instead of continuing."],"exampleFix":"// chaincode-side before\niter, _ := stub.GetStateByRange(start, end)\n// ...long processing...\niter.HasNext() // peer may have expired iterator\n// after: consume and close promptly\niter, _ := stub.GetStateByRange(start, end)\nfor iter.HasNext() {\n\tkv, _ := iter.Next()\n\tprocess(kv)\n}\niter.Close()","handlingStrategy":"validation","validationCode":"// chaincode-side: ensure the iterator is used before it expires and not after Close\nif iter == nil {\n\treturn shim.Error(\"iterator missing: re-run the original query\")\n}","typeGuard":null,"tryCatchPattern":"iter, err := stub.GetStateByRange(start, end)\nif err != nil { return shim.Error(err.Error()) }\ndefer iter.Close()\nfor iter.HasNext() {\n\tkv, err := iter.Next()\n\tif err != nil {\n\t\tif strings.Contains(err.Error(), \"query iterator not found\") {\n\t\t\t// iterator expired on peer; restart the query\n\t\t\treturn shim.Error(\"iterator expired; re-issue query\")\n\t\t}\n\t\treturn shim.Error(err.Error())\n\t}\n}","preventionTips":["Consume and close iterators promptly, inside one transaction","Do not hold iterators across long computations or sleeps","Avoid calling Next after Close","Tune peer queryIterator TTL for large result processing"],"tags":["fabric","iterator","state-query","lifecycle"],"backgroundTag":"query-iterator-not-found","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"}