What values are returned by Datastores for players who have never played before?

I’m a little confused. Does it just return nil?

GlobalDataStore::GetAsync returns void (C term for no value) when there is no value.

1 Like

So what do I compare this to? If I want to check if the player’s datastore has value in it or not, what do I do? Is nil appropriate?

Sure, nil would be appropriate in your case.

1 Like

I believe you could do

if dataStore:GetAsync(player.UserId) ~= nil then
    -- player has data
else
    -- player doesn't have data
end

Not entirely sure though, I mostly use DataStore2

1 Like

If doesn’t exist, then make a new one or do a retry

local data = Stuff:GetAsync(userId) or {
		MX = "None"
        Slots = {}
		Info = {Swag = true, Cash = 0}
	}

cc @DataErased @kenami

While you can substitute another value for if GetAsync returns a falsy or empty value, please never actually do this in production. GetAsync will fail or return incorrect values if there’s a DataStore outage and this kind of code is the most prone to data loss incidents.

You should always be working with pcall when it comes to DataStore and using the success boolean to determine if your code was able to interact with the DataStoreService successfully and what has been returned from it. Only do that kind of if checking when it comes to the returned value.

local success, ret = pcall(function ()
    return dataStore:GetAsync(player.UserId)
end)

if success then
    -- Successful use of DataStoreService
    if ret then
        -- Data in DataStore
    else
        -- No data in DataStore
    end
else
    -- Unsuccessful use of DataStoreService
end

The only case you have to worry about with the above, assuming you also block save requests against players who had loading errors to prevent data corruption, is incidents where DataStores are returning cached or incorrect values but the DataStoreService call was still successful. There has been one incident like this before in which Roblox provided rollback DataStores to help restoration of lost data.

If you don’t want to manually do all this work, you can always create or use a DataStore wrapper as well. I have my own wrapper and raw code that’ll change between Set and UpdateAsync depending on what happened to the player during loading or reject saves altogether if all fails. DataStore2 provides a lot of useful DataStore tooling, from caching to backups.

2 Likes

I had completely forgot about using pcalls in this scenario because I usually use DataStore2, which I believe uses pcalls in its module :sweat_smile: Good call though, thanks for the useful insight.

I’ve barely worked with Datastores, so I think, uh, I might just go with DataStore2 since it seems to cover a lot of the bulky things.