Error with datastore and loading. What's going wrong?

Hello. I’m new to posting to the dev forum, so bare with me.
I made this simple datastore script that should load the datastore and add the values to your leaderstats. It fails at line 29, which is marked in the script. What am I doing wrong?

local dts = game:GetService("DataStoreService")
local money = dts:GetDataStore("Currency-0")



--Currency is set up like this:

--{CASH, GEMS}

--It is a table storing both values.


game.Players.PlayerAdded:Connect(function(plr)
local model = Instance.new("Model") -- lets set up our leaderstats!
	model.Name = "leaderstats"
	model.Parent = plr
local moneyValue = Instance.new("IntValue")
	moneyValue.Name = "Cash"
local gemValue = Instance.new("IntValue")
	gemValue.Name = "Gems"
	
local key = "USER_" .. plr.Name .. "_" .. plr.UserId -- advanced player key

local storedCash -- setting up a variable
local success, err = pcall(function()
	storedCash = money:GetAsync(key)
end)
if success then
	moneyValue.Value = storedCash[1] -- this is the line that messes up
	gemValue.Value = storedCash[2]
	-- we've set that, now we must make it show
	moneyValue.Parent = model
else
	moneyValue.Value = 0
	gemValue.Value = 0
	money:SetAsync(key, {0, 0}) 
end
end)

My error: :29: attempt to index local 'storedCash' (a nil value)

When you do GetAsync, it probably returns nil, since you haven’t written anything to that key. That’s why storedCash is nil, and it produces an error when you try indexing it.

Also, you’re doing datastore error handling wrong. If GetAsync produces an error, you will basically delete your player’s data. Instead, when it produces an error, you should instead either stop the function or try getting the data again.

So, instead of

local success, err = pcall(function()
	storedCash = money:GetAsync(key)
end)
if success then

You should have something like

local success,err
repeat
	success,err = pcall(function()
		storedCash = money:GetAsync(key)
	end)
until success or not wait(5) --if there is an error, wait 5 seconds, instead stop the loop

if storedCash then --Checking if the player has saved data
2 Likes

Thanks, datastores are not my forte, and I’m glad you responded quickly. Have a good day! :grinning:

That’s not how you use the until statement. Your until statement with the wait is saying “if wait(5) doesn’t return anything”, which is just as much a terrible abuse of the until statement as using it for the while condition. It’s bad for readability as well.

This is what I would do instead:

local success, result do
    repeat
        success, result = pcall(money.GetAsync, money, key)
        if not success then
            wait(5)
        end
    until success or MAX_RETRIES

A note on MAX_RETRIES: this is a placeholder making a note that you should add a retry cap. Repeatedly calling this function is bad use of DataStores. It would create a loop that runs forever until DataStores return true, which can cause an issue if DataStores are down or the call is not succeeding. I’m not sure why you would use a loop statement with data anyway.

The simple response here is to do error handling. If there’s no data in the key (which then GetAsync returns nil), you handle that case instead of making a loop.

local success, result = pcall(money.GetAsync, money, key)
if success then
    if result then
        -- Data non-nil
    else
        -- Data nil
    end
else
    -- Success false, do something about it
end
1 Like