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
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