Issue with DataStores

Hi!

I’m writing my PlayerSetup script, to set up the leaderboard and player data when people connect, and for some reason, when loading data from my DataStore, it’s jumping to ‘success’, even though it’s apparently “attempting to index nil with a number”. I really can’t figure out what’s causing this.

PlayerSetup snippet
	-- max height record
	local maxHeight = Instance.new('IntValue')
	maxHeight.Name = 'Record'
	maxHeight.Parent = leaderstats
	
	local data
	local success, err = pcall(function()
		data = playerDS:GetAsync(player.UserId)
	end)
	
	if success then
		maxHeight.Value = data[1]
		money.Value = data[2]
	else
		print("The player has no data!") -- will default to 0
	end

(Note: It’s erroring on the maxHeight, no idea if ‘money’ will work or not.)

2 Likes

I don’t work with datastores very often, but from a cursory reading of your snippet, it appears that the issue would be that the data variable is not getting declared correctly. It’s evident that the call is being made from pcall properly (as the success state is obviously coming back true). Perhaps you might find this article helpful:

1 Like

Well, yes, but my point is ‘success’ shouldn’t be returning true, if it seemingly can’t find the table it’s supposed to be looking for.

Do you know for a fact that that datastore you’re calling is not initialized to have a value for the call you are making?

Considering I have only just started using DataStores in my game, yes.
Oh, and nothing’s showing up in DataStore editor.

Alright! From what I remember from Datastores, usually calling a GetAsync on a key that doesn’t exist yet will just return nil instead of responding with an error, so the pcall is likely not erroring out. In the api reference, they achieve a similar effect using

local myGold
local success, err = pcall(function()
    myGold = goldDataStore:GetAsync(playerKey) or STARTING_GOLD
end)
if success then
	gold.Value = myGold
else
	-- Failed to retrieve data
end

The “or” in the pcall initializes the value if the GetAsync is not storing a value for the specified key yet, and then the pcall is meant to protect against erroring in this situation.

But the error I’m getting seems to be that the… maxHeight is ‘nil’, not the datastore, actually…
‘trying to index nil with number’ sounds like it can’t find maxHeight. But putting player.CharacterAdded:Wait() in the script just causes it to hang.

Can you post the direct error here?

[04:23:21.001 - ServerScriptService.PlayerSetup:38: attempt to index nil with number]

Yeah, my guess is that the data variable is being assigned nil, and then when it tries to assign that to the int value it causes the error you’re seeing. Trying adding an “or 0” to the end of the GetAsync line and see if you get any more luck.

Nope. Same error. Like I said, I’m pretty sure it’s not detecting maxHeight, since it’s trying to put a number in ‘nil’, apparently.

Not sure how it wouldn’t be detecting an int variable unless leaderstats isn’t defined for it to be parented to, but even that shouldn’t matter.

0[1] would error just like nil[1] does. The actual solution here is just checking if data exists and, if not, setting up default values for all its keys. Something like or {0, 0} would work.

@H_Baguette: pcall fails when it can’t retrieve data, not when it knows there is no data to receive.

3 Likes

I think this is your issue and why it isn’t working

	local data   -- data is nil here just setup variable
	local success, err = pcall(function()   
		data = playerDS:GetAsync(player.UserId)  -- this is accessing the datastore but returning nil because there is no data on the first Get...  you have to save some data to return something other than nil
	end)
	
	if success then  -- it is true because the datastore returned the GetAsync fine but it is Nil(data)
		maxHeight.Value = data[1]   -- then you are trying to access Nil here which is data  with a number which is the [1]
		money.Value = data[2]
	else
		print("The player has no data!") -- will default to 0
	end

to fix this the below code should work by setting default data if there isn’t any

	local data
	local success, err = pcall(function()
		data = playerDS:GetAsync(player.UserId)
	end)
	
	if success then
		if data then  -- player has data so load it into values
			maxHeight.Value = data[1] 
			money.Value = data[2]
		else  -- player has no data so set some defaults
			maxHeight.Value = 0  
			money.Value = 0
			print("The player has no data!") -- will default to 0
		end
	else
		print('The Datastore did not Load')
	end

A few things that could help resolve this easier next time would be:

the save function part of the script so we can see how you are setting up and saving the actual data…
also is this a ordered datastore or just a normal one you are using
the full error you are getting

1 Like

I should really stop trying to program when it’s five in the morning and I haven’t slept. Looking back on this thread, yeah, it seems pretty obvious what I was doing wrong. Thanks.

1 Like