ListKeysAsync with cursor, then AdvanceToNextPageAsync cursor stay fixed

Below is a simple script for the bug report. we use ListKeysAsync to get a page. If we didn’t provide the cursor parameter, then subsequence call to AdvanceToNextPageAsync will change the pages.Cursor every time. However, if cursor was provided, the first Cursor is immediately advanced, and then it stays the same forever afterwards.

local OCUserNotification = require(game:GetService("ServerScriptService").OpenCloud.V2.UserNotification)
local DataStoreService = game:GetService("DataStoreService")

local global = DataStoreService:GetGlobalDataStore()
local storedCursor = nil
-- storedCursor = global:GetAsync("StoredCursor") -- previous stored cursor, uncomment to see the bug
print("storedCursor", storedCursor)

local dataStore = DataStoreService:GetDataStore("dev001")
local pages = dataStore:ListKeysAsync("Player_", 20, storedCursor, true)

local data = pages:GetCurrentPage()
print("current Cursor", pages.Cursor)
-- process data

if not pages.IsFinished then
	pages:AdvanceToNextPageAsync()
	print("next Cursor", pages.Cursor)
	data = pages:GetCurrentPage()
	-- process data
end

if not pages.IsFinished then
	pages:AdvanceToNextPageAsync()
	print("next next Cursor", pages.Cursor)
	data = pages:GetCurrentPage()
	-- process data
end

Example output when no cursor is provided

  19:19:15.492  storedCursor nil  -  Server - Script:6
  19:19:15.893  current Cursor o2vUnFaVyxDNhITzOgyi8VaakDo6jApixl0yjyrePKEzIw==  -  Server - Script:12
  19:19:16.243  next Cursor nzrxiER/+KVBNMl9B7mbqnzqkKsBZcr9liT+cwLGGf01Iw==  -  Server - Script:16
  19:19:16.563  next next Cursor b7VcHh8kM6oR2Uwi7eKlmGisrwUjMHDV9M792z7YaiM2Iw==  -  Server - Script:23

Example output when stored cursor is provided

  19:15:26.627  storedCursor o2vUnFaVyxDNhITzOgyi8VaakDo6jApixl0yjyrePKEzIw==  -  Server - Script:6
  19:15:27.051  current Cursor nzrxiER/+KVBNMl9B7mbqnzqkKsBZcr9liT+cwLGGf01Iw==  -  Server - Script:12
  19:15:27.416  next Cursor nzrxiER/+KVBNMl9B7mbqnzqkKsBZcr9liT+cwLGGf01Iw==  -  Server - Script:16
  19:15:27.756  next next Cursor nzrxiER/+KVBNMl9B7mbqnzqkKsBZcr9liT+cwLGGf01Iw==  -  Server - Script:23

Expected behavior

We expect the pages.Cursor will not update before AdvanceToNextPageAsync is called. And subsequence AdvanceToNextPageAsync will move to next page just like it does when no cursor was provided

1 Like

Thanks for the report! We’ll follow up when we have an update for you.

1 Like

Hello! I am looking into this now. Just curious, when did you notice this start happening?

1 Like

I posted as soon as I encountered this, so I don’t know when it started.

We found similar issue in our project. We got pages by GetCurrentPage on our OrderedDatastores.

local success, pages = pcall(function()
    return store:GetSortedAsync(false, 50)
end)

while true do
    local entries = pages:GetCurrentPage()
    for _, entry in entries do
        -- do something
    end
    if pages.IsFinished then
        break
    else
        pages:AdvanceToNextPageAsync()
    end
end

If we print entries returned by the GetCurrentPage function, previous page’s data is printed even if there are no more data in our OrderedDataStore. However, IsFinished is not always false, it returns true after a certain number of attempts. The number varies by the data store.

I’ve been aware of this issue since around January 15th.

1 Like