My datastore script isn't working, please help!

Hello, I have a major problem with my Datastore script.
Yesterday, I have tried remaking and optimizing it, as I was using Alvinblox’s tutorial for Datastore scripts and that lead me to making the mistake of calling GetAsync or SetAsync several times for each value.

I have worked with others in a server to produce this script as a result:

-- local DataStoreService = game:GetService("DataStoreService")
local NKODataStore = DataStoreService:GetDataStore("NKODataStore")
local leaderstatsFolderVals = {"Level", "Kills"}
local statsFolderVals = {"CoinAmount", "EXPAmount", "Kills"}
-- This would be data that would be provided if the player was new

local defaultData = {
	["CoinAmount"] = 0,
	["EXPAmount"] = 0,
	["Kills"] = 0
}

local function createDataTable(plrObj)
	-- Creates a table that is easier to save into a DataStore
	local DataTable = {}

	for _, name in ipairs(statsFolderVals) do
		DataTable[name] = 0
	end
	return DataTable
end

local function GetKey(plrObj: Player)
	return "user-"..plrObj.UserId
end

local function getDataFromDatastore(plrObj: Player)
	-- Don't call getDataFromDatastore too often, as it counts against the rate limit
	local success, data = pcall(function()
		return NKODataStore:GetAsync(GetKey(plrObj))
	end)
	if not success then
		-- Data could not be loaded
		print("Data was not loaded.")
		-- We return 'nil' to tell the scripts we have to stop what they're doing
		return nil
	end
	if data == nil then
		-- This player is new
		return defaultData
	end
	-- There was data before, so we return it
	return data
end

local function AddValues(plrObj: Player)
	-- Creating NumberValues inside of Player.leaderstats
	local leaderstats = Instance.new("Folder", plrObj)
	leaderstats.Name = "leaderstats"
	for _, valName in ipairs(leaderstatsFolderVals) do
		local numVal: NumberValue = Instance.new("NumberValue")
		numVal.Name = valName
		numVal.Parent = leaderstats
	end
	-- Creating NumberValues inside of Player.Statistics
	local Statistics = Instance.new("Folder", plrObj)
	Statistics.Name = "Stats"
	for _, statName in ipairs(statsFolderVals) do
		local statVal: NumberValue = Instance.new("NumberValue")
		statVal.Name = statName
		statVal.Parent = Statistics
	end
	-- Now, we load the data from a datastore and set it to the NumberValues created before!
	local SavedData = getDataFromDatastore(plrObj)
	print(SavedData)
	for name, val in pairs(SavedData) do
		local valObj = Statistics:FindFirstChild(name)

		if valObj then
			valObj.Value = val
		end
	end
end
local function saveData(plrObj: Player)
	local success, errorMsg = pcall(function()
		NKODataStore:UpdateAsync(GetKey(plrObj), function(previousData)
			-- :UpdateAsync() is much more safer to use, at the cost of having to use a callback
			return createDataTable(plrObj.UserId)
		end)
	end)
	if success then
		print("Player data saved successfully")
	else
		-- Might wanna warn the player that their data couldn't be saved
		print("There was an error while saving player data")
		warn(errorMsg)
	end
end

game.Players.PlayerAdded:Connect(AddValues)
game.Players.PlayerRemoving:Connect(saveData)

while true do
	-- Save periodically
	for _, plrObj in ipairs(game.Players:GetPlayers()) do
		if plrObj ~= nil then
			saveData(plrObj)
			task.wait(5)
		end
	end
	task.wait(90)
end

Now, the problem I have is that on this function here, on line 67. The table, SavedData is nil for some reason. Thus, it is not loading any data.

local SavedData = getDataFromDatastore(plrObj)
	print(SavedData)
	for name, val in pairs(SavedData) do
		local valObj = Statistics:FindFirstChild(name)

		if valObj then
			valObj.Value = val
		end
	end

I would like to solve this error myself but frankly, I’m stumped, especially when it comes to tables.

Thanks!

3 Likes

The error in particular says this: invalid argument #1 to 'pairs' (table expected, got nil)

There should be a number indicating at which line that error occurred, could you share it?

2 Likes
local SavedData = getDataFromDatastore(plrObj)
print(SavedData)
if type(SavedData) == "table" then
	for name, val in pairs(SavedData) do
		local valObj = Statistics:FindFirstChild(name)

		if valObj then
			valObj.Value = val
		end
	end
end

You can check what type of value is being stored by “SavedData”, it should be a table as expected if data is loaded and will be nil if otherwise, then you can act accordingly.

The error is on line 67, where it loops though SavedData