Datastore not working

New code:

local DDS = game:GetService("DataStoreService"):GetDataStore("DataThingy")

game.Players.PlayerAdded:Connect(function(Plr)
	
	
	local stats = Instance.new("Folder", Plr)
	stats.Name = "leaderstats"
	
	local levels = Instance.new("IntValue", stats)
	levels.Name = "Levels"
	
	local exp = Instance.new("IntValue", stats)
	exp.Name = "Exp"
	
	local data 
	local suc, err = pcall(function()
		data = DDS:GetAsync("key_"..Plr.UserId)
	end)
	if not suc then
		warn(err)
	else
		levels.Value = data['Level'] or 0
		exp.Value = data['Exp'] or 0
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local leaderstatsInTable = {
		Level = plr.leaderstats.Levels.Value,
		Experience = plr.leaderstats.Exp.Value
	}
	
	local data 
	local suc, err = pcall(function()
		data = DDS:SetAsync("key_"..plr.UserId, leaderstatsInTable)
	end)
	if not suc then
		warn(err)
	end
end)

If the data doesn’t exist in the DataStore, it will return nil.
This is where the error is coming from, as when it passes the check to see if the DataStore request was successful, it tries to index data that doesn’t exist (nil!), and therefore it throws the error “attempt to index number with nil”.

To fix it, you could add a check to see if the data exists and if so then use the data table, or just put a default value.
It would look something like this:

local Success, Data = pcall(DDS.GetAsync, DDS, "key_" .. Plr.UserId)
if not Success then
	warn(Data)
else
	if Data then
		levels.Value = data["Level"]
		exp.Value = data["Experience"]
	else
		levels.Value = 0
		exp.Value = 0
	end
end

Aren’t those two If statements the same?

i would take the leaderboard stats, create a table of the values, JSON serialize and save… and deserialize and set the values when you do your GetAsync…

1 Like
local DDS = game:GetService("DataStoreService"):GetDataStore("DataThingy")

game.Players.PlayerAdded:Connect(function(Plr)
	
	
	local stats = Instance.new("Folder")
	stats.Name = "leaderstats"
    stats.Parent = Plr
	
	local levels = Instance.new("IntValue")
	levels.Name = "Levels"
    levels.Parent = stats
	
	local exp = Instance.new("IntValue")
	exp.Name = "Exp"
    exp.Parent = stats
	
	local data 
	local suc, err = pcall(function()
		data = DDS:GetAsync("key_"..Plr.UserId)
	end)
	if not suc then
		warn(err)
	else
		levels.Value = data[Level]
		exp.Value = data[Experience]
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local leaderstatsInTable = {
		Level = plr.leaderstats.Levels.Value;
		Experience = plr.leaderstats.Exp.Value;
	}
	
	local data 
	local suc, err = pcall(function()
		local data = DDS:SetAsync("key_"..plr.UserId, leaderstatsInTable)
	end)
	if not suc then
		warn(err)
	end
end)

Try using this and let me know if it works :slight_smile:

They’re not the same, as he’s still trying to index something that doesn’t exist, with an or statement with it.
In my example, I check if the data actually exists before indexing any keys with it. This prevents it from throwing an error, in the case it doesn’t exist.

Doing it with the semicolon didn’t work. Also, I thought it didn’t matter whether or not I used a comma or semicolon.

[ServerScriptService.Put in SSS:36: attempt to concatenate string with table]

just to let all of you guys know, this came out from the pcall in PlayerRemoving.

Yeah lol i realized that after writing it. Sorry for that lmao. Had a brain fart.
However, you should still parent new instances on separate lines as it results in much faster times.

And you said using the script that guidable provided didn’t work?

1 Like

Can I get an example of this? I’ve seen this many times in other threads but it has been confusing to me.

I mean the one Guidable put didn’t make any sense. Aren’t the If statements that he put the exact same?

yeah i looked at it again, and the data value seems to be misplaced.

local DDS = game:GetService("DataStoreService"):GetDataStore("DataThingy")

game.Players.PlayerAdded:Connect(function(Plr)
	
	
	local stats = Instance.new("Folder", Plr)
	stats.Name = "leaderstats"
	
	local levels = Instance.new("IntValue", stats)
	levels.Name = "Levels"
	
	local exp = Instance.new("IntValue", stats)
	exp.Name = "Exp"
	
	local data 
	local suc, err = pcall(function()
		data = DDS:GetAsync("key_"..Plr.UserId)
	end)
	if not suc then
		warn(err)
	else if data then
		levels.Value = data.Level or 0
		exp.Value = data.Exp or 0
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local leaderstatsInTable = {
		Level = plr.leaderstats.Levels.Value,
		Experience = plr.leaderstats.Exp.Value
	}
	
	local data 
	local suc, err = pcall(function()
		data = DDS:SetAsync("key_"..plr.UserId, leaderstatsInTable)
	end)
	if not suc then
		warn(err)
	end
end)

You’re supposed to check that the data exists and wasn’t corrupt otherwise it will return an error in your PlayerAdded event. This should work.

local DDS = game:GetService("DataStoreService"):GetDataStore("DataThingy")

game.Players.PlayerAdded:Connect(function(Plr)
	
	
	local stats = Instance.new("Folder", Plr)
	stats.Name = "leaderstats"
	
	local levels = Instance.new("IntValue", stats)
	levels.Name = "Levels"
	
	local exp = Instance.new("IntValue", stats)
	exp.Name = "Exp"
	
	local data 
	local suc, err = pcall(function()
		data = DDS:GetAsync("key_"..Plr.UserId)
	end)
	if not suc then
		warn(err)
	elseif data then
		print("Success")
		levels.Value = data.Level
		exp.Value = data.Experience 
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local leaderstatsInTable = {
		Level = plr.leaderstats.Levels.Value;
		Experience = plr.leaderstats.Exp.Value
	}
	
	local data 
	local suc, err = pcall(function()
		data = DDS:SetAsync("key_"..leaderstatsInTable)
	end)
	if not suc then
		print(err)
	end
end)

This is my current code. I did the check that you told me to and it was able to run the “Success” print but it would then error at levels.Value = data.Level

local DDS = game:GetService("DataStoreService"):GetDataStore("DataThingy")

game.Players.PlayerAdded:Connect(function(Plr)
	
	
	local stats = Instance.new("Folder", Plr)
	stats.Name = "leaderstats"
	
	local levels = Instance.new("IntValue", stats)
	levels.Name = "Levels"
	
	local exp = Instance.new("IntValue", stats)
	exp.Name = "Exp"
	
	local data 
	local suc, err = pcall(function()
		data = DDS:GetAsync("key_"..Plr.UserId)
	end)
	if not suc then
		print(err)
	elseif data then
		print("Success")
		levels.Value = data
		--exp.Value = data.Experience 
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local leaderstatsInTable = {
		Level = plr.leaderstats.Levels.Value;
		Experience = plr.leaderstats.Exp.Value
	}
	
	local data 
	local suc, err = pcall(function()
		data = DDS:SetAsync("key_"..plr.leaderstats.Levels.Value)
	end)
	if not suc then
		print(err)
	end
end)

I ran this code to check if the datastore will run by only loading one value without the table. It was able to set data (the print outputted “Success”) but when it tried to save the data when I left, it outputted “Argument 2 missing or nil”.

It looks like you’re concatenating the string “key_” with the levels value

local suc, err = pcall(function()
	data = DDS:SetAsync("key_"..plr.leaderstats.Levels.Value)
end)

Correct:

local suc, err = pcall(function()
	data = DDS:SetAsync("key_"..plr.UserId, plr.leaderstats.Levels.Value)
end)

Sorry i didn’t notice that before, but it’s like that in every script example.

That actually might be the error.

I fixed the arguments. It might be I am doing the tables wrong.

So I tried it without the table and no errors came out but it wouldn’t save.

local DDS = game:GetService("DataStoreService"):GetDataStore("DataThingy")

game.Players.PlayerAdded:Connect(function(Plr)
	
	local stats = Instance.new("Folder")
	stats.Name = "leaderstats"
	stats.Parent = Plr
	
	local levels = Instance.new("IntValue")
	levels.Name = "Levels"
	levels.Parent = stats
	
	local exp = Instance.new("IntValue")
	exp.Name = "Exp"
	exp.Parent = stats
	
	local data 
	local suc, err = pcall(function()
		data = DDS:GetAsync("key_"..Plr.UserId)
	end)
	if suc then
		if data then
			levels.Value = data.Level or 0
			exp.Value = data.Exp or 0
		end
	else warn(err) end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local leaderstatsInTable = {
		Level = plr.leaderstats.Levels.Value,
		Experience = plr.leaderstats.Exp.Value
	}
	
	local data 
	local suc, err = pcall(function()
		data = DDS:SetAsync("key_"..plr.UserId, leaderstatsInTable)
	end)

	if suc then
		print("Success!")
	else
		warn(err)
	end
end)

does this work?