{"record":{"id":"ca7eacf2b1e9d5e9","repo":"redis/jedis","slug":"failed-to-delete-cursor","errorCode":null,"errorMessage":"Failed to delete cursor {}: {}","messagePattern":"Failed to delete cursor (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src/main/java/redis/clients/jedis/search/aggr/AggregateIterator.java","lineNumber":175,"sourceCode":"\n    // NOTE(imalinovskyi): If we use single connection to execute commands, we're not\n    // responsible for closing it here.\n  }\n\n  /**\n   * Deletes the cursor on the server to free resources. This method is idempotent and safe to call\n   * multiple times.\n   */\n  private void deleteCursor() {\n    if (cursorId != null && cursorId > 0) {\n      CommandArguments args = new CommandArguments(SearchProtocol.SearchCommand.CURSOR)\n          .add(SearchProtocol.SearchKeyword.DEL).add(indexName).add(cursorId);\n      try {\n        // Delete the cursor to free server resources\n        executeCommand(args);\n      } catch (Exception e) {\n        // Log but don't throw - cursor will expire naturally\n        logger.warn(\"Failed to delete cursor {}: {}\", cursorId, e.getMessage());\n      }\n    }\n  }\n\n  private AggregationResult doFetch() {\n    if (cursorId == null || cursorId <= 0) {\n      return null;\n    }\n\n    CommandArguments args = new CommandArguments(SearchProtocol.SearchCommand.CURSOR)\n        .add(SearchProtocol.SearchKeyword.READ).add(indexName).add(cursorId);\n\n    // Only add COUNT argument if a batch size was explicitly specified\n    if (batchSize != null) {\n      args.add(SearchProtocol.SearchKeyword.COUNT).add(batchSize);\n    }\n\n    Object rawReply = executeCommand(args);","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/search/aggr/AggregateIterator.java#L157-L193","documentation":"AggregateIterator deletes the server-side cursor of a FT.AGGREGATE cursor-based aggregation when the iteration is closed or removed. If the cursor deletion command fails, this warning is logged instead of throwing, because the cursor will expire naturally on the server and the user's close() should not fail. The exception message (not the exception) is included in the log.","triggerScenarios":"Calling close() or remove() on an AggregateIterator whose CURSOR DEL command fails: connection dropped mid-aggregation, server restarted, cursor already expired/deleted, or search module error.","commonSituations":"Abandoning aggregations early in apps with unstable connections; Redis Stack search module restarted between fetches; cursor left idle past its TTL so the DEL arrives on an already-gone cursor; network blips during result processing.","solutions":["No user action required — the cursor expires server-side; treat the warning as informational.","If warnings are frequent, check connection stability and pool health to the search endpoint.","Ensure the iterator is consumed or closed promptly so cursors are deleted before TTL expiry.","Upgrade jedis/search module if you see repeated failures on valid cursors (protocol bugs)."],"exampleFix":"// before\ntry (AggregateIterator it = ...; ) { consume(it); } // warnings ignored by design\n// after\n// nothing to change: close() deliberately swallows cursor-delete errors","handlingStrategy":"try-catch","validationCode":"// ensure the connection is healthy before long aggregations\nif (!jedis.isConnected()) jedis = reconnect();","typeGuard":null,"tryCatchPattern":"try (AggregateIterator it = jedis.ftAggregateCursor(...)) {\n  while (it.hasNext()) consume(it.next());\n} // close() handles cursor deletion; failures are logged, not thrown","preventionTips":["Close aggregation iterators promptly (try-with-resources)","Don't hold cursors idle longer than their TTL","Keep connections to the search endpoint stable (pools, keepalive)","Treat the warning as informational — cursors expire server-side"],"tags":["redis","search","cursor","cleanup"],"backgroundTag":"resource-not-found","analyzedSha":"6dac31d4c224fb3257c216f3985340c6f500cdcb","analyzedAt":"2026-09-08T04:55:01.204Z","contentChangedAt":"2026-09-08T04:55:01.204Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}