Help Needed | Data Store script not working

I’m currently using tables to sort out my data store since I have a lot of values. To test, currently I’ve made a very small table since it’s my first time using tables for data stores but it isn’t working as intended.

local DataStoreService = game:GetService("DataStoreService")
local ValuesDataStore = DataStoreService:GetDataStore("ValuesDataStore")

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")

local Data = ServerStorage:WaitForChild("Data")
local LeaderstatsFolder = Data:WaitForChild("leaderstats")

Players.PlayerAdded:Connect(function(Player)
	
	Data.Parent = Player
	LeaderstatsFolder.Parent = Player
	
	Values = {
		Points = Player.leaderstats.Points.Value;
		Level = Player.leaderstats.Level.Value;
    }
	
	
	local Player_Data
	
	local success, errormessage = pcall(function()
	    Player_Data = ValuesDataStore:GetAsync(Player.UserId .. "ValuesData", Values)
	end)	
	
	if success then
		Values = Player_Data
	else
		error(errormessage)
	end
	
end)

Players.PlayerRemoving:Connect(function(Player)
	
	local success, errormessage = pcall(function()
		ValuesDataStore:SetAsync(Player.UserId .. "ValuesData", Values)
	end)
	if success then
		print(Player.Name .. " 's data saved")
	else
		print("Error saving " .. Player.Name .. 's data!')
		error(errormessage)
	end
end)


It does print data saved though I cannot understand why it doesn’t save.

image

API services are enabled.

Well you have SetAsync instead of get. Where it says errormessage.

That isn’t the problem.

( 30 characters )

The problem is, you aren’t saving data when the player is in game, you just are storing the player data and saving when the player leaves, thats not really secure to do a DataStore system, i totally recommend use game:BindToClose and save the data when the player closes the game instead saving when the player is leaving, your pcalls aren’t really secure because Player_Data is nil, and if you make it as a value in a pcall it will be nil, but not marked as error.

Your script:

local DataStoreService = game:GetService("DataStoreService")
local ValuesDataStore = DataStoreService:GetDataStore("ValuesDataStore")
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Data = ServerStorage:WaitForChild("Data")
local LeaderstatsFolder = Data:WaitForChild("leaderstats")
local TrySave = 1
local DataLoaded = false

local function GetPlayer(Player)
	local Key = "Player-".. Player.UserId
	local CountSave = 0
	local Data = nil
	local Sucess,Error
	repeat -- I totally recommend this, is more secure if some error happends
		Sucess,Error = pcall(function()
			Data = ValuesDataStore:GetAsync(Key) -- We store the data player (secure method is using pcalls with values)
		end)
		CountSave = CountSave + 1 -- Tries to save the data
	until CountSave >= TrySave or Sucess -- Stop repeating when the save has sucess
	if not Sucess then -- This is normal on pcalls, you just can modify this part and try to save the data
		warn(Player.Name.."Data failed to load:".. tostring(Error)) -- We have the error as a warning.
		Player:Kick("Error, no data in player ".. tostring(Error)) -- This will kick the player if there is no data or your API is off
		return
	end
	if Sucess then -- If save has worked
		if Data then -- If data is not nil
			return Data -- I have no imagination to script that
		else
			return {
			["Money"] = 0, -- Add all your values to save here  [0 means the starting money]
			}
		end
	end -- OMG IT SAYS END
end

local function SetPlayer(Player)
	if DataLoaded then -- If data worked, not recommend to remove this
		local Key = "Player-".. Player.UserId -- This is for all DataStores
		local SaveCount = 0 -- Tries to save
		local Sucess,Error -- The same, you can use local Sucess,Error = pcall
		local Data = {
			["Money"] = Player:WaitForChild("leaderstats").Money.Value, -- Remember to change this with ur properties
		}
		repeat -- I recommend to repeat the data until its sucess
			Sucess,Error = pcall(function()
				ValuesDataStore:SetAsync(Key,Data) -- We save the player data, if some data is found in him.
			end)
			SaveCount = SaveCount + 1 -- Tries to save until sucess is true
		until SaveCount >= TrySave or Sucess -- Yes.
		if not Sucess then -- We rejoin and we save the data, so i recommend the kick function or it will keep warning
			Player:Kick("Data failed to save, please rejoin!")
			return
		end
	else
		return
	end
end

local function CreateStats(Player) -- A normal leaderboard creating script breh
	local Values = GetPlayer(Player)
	local Leaderstats = Instance.new("Folder")
	Leaderstats.Name = "leaderstats"
	Leaderstats.Parent = Player
	local Money = Instance.new("IntValue")
	Money.Name = "Money"
	Money.Parent = Leaderstats
	Money.Value = Values.Money
	DataLoaded = true -- Dont change
end

game:BindToClose(function() -- Better than PlayerRemoving because we get the children of players and save their stats.
	for  _,v in next, Players:GetChildren() do
		if v then
			SetPlayer(v)
		end
	end
end)

Players.PlayerRemoving:Connect(SetPlayer)
Players.PlayerAdded:Connect(CreateStats)

Hope this helped you!

I don’t believe since without tables, it works perfectly fine though.

It can works without tables aswell, it worked for me and saves every times i tried.

But I want to use tables, why doesn’t it save then?

Because your Data has no key, and you aren’t saving all table content in the script, you are using pcalls so you just will be marked as “Data Saved” but you just saved 1 property of table, instead 2.

Yeah but not even 1 saves.

( 30 characters )

You forgot the key, i just mean, if you added key, just 1 data of table will save.

Forgot local Key = “Player-”… Player.UserId

local DataStoreService = game:GetService("DataStoreService")
local ValuesDataStore = DataStoreService:GetDataStore("ValuesDataStore")

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")

local Data = ServerStorage:WaitForChild("Data")
local LeaderstatsFolder = Data:WaitForChild("leaderstats")

Players.PlayerAdded:Connect(function(Player)
	
	Data.Parent = Player
	LeaderstatsFolder.Parent = Player
	
	Values = {
		 Player.leaderstats.Points.Value; 
		 Player.leaderstats.Level.Value;
	}
	
	
	local Player_Data
	local success, errormessage = pcall(function()
	    Player_Data = ValuesDataStore:GetAsync(Player.UserId .. "-ValuesData", Values)
	end)	
	
	if success then	
		Player.leaderstats.Points.Value = Player_Data
	else
		error(errormessage)
	end
	
end)

Players.PlayerRemoving:Connect(function(Player)
	
	local success, errormessage = pcall(function()
		ValuesDataStore:SetAsync(Player.UserId .. "-ValuesData", Values)
	end)
	
	if success then
		print(Player.Name .. " 's data saved")
	else
		print("Error saving " .. Player.Name .. 's data!')
		error(errormessage)
	end
end)

Fixed it but now data still doesn’t save.

I can understand why everyone is using this specific type of data store system but this tends to have bugs and etc. If you can’t get it fixed from more comments then use a new system that’ll be easier to understand.

Im just trying to help him remaking his script, i dont use a “type” of DataStore system, i use diffenrent DataStores for diffenrent games