Why is my game experiencing dataloss?

My script looks like this:

local function TableValues(Player)
	local Player_stats = {}
	
	for i, v in pairs(Player.leaderstats:GetChildren()) do
		Player_stats[v.Name] = v.Value
	end
	
	for i, v in pairs(Player.ValuesFolder:GetChildren()) do
		Player_stats[v.Name] = v.Value
	end
	
	for i, v in pairs(Player.Settings:GetChildren()) do
		Player_stats[v.Name] = v.Value
	end
	
	for i, v in pairs(Player.Codes:GetChildren()) do
		Player_stats[v.Name] = v.Value
	end
	
	for i, v in pairs(Player.DnaOwned:GetChildren()) do
		Player_stats[v.Name] = v.Value
	end
	
	for i, v in pairs(Player.EquippedFolder:GetChildren()) do
		Player_stats[v.Name] = v.Value
	end
	
	for i, v in pairs(Player.RanksOwned:GetChildren()) do
		Player_stats[v.Name] = v.Value
	end
	
	for i, v in pairs(Player.ToolsOwned:GetChildren()) do
		Player_stats[v.Name] = v.Value
	end
	
	return Player_stats
end

game.Players.PlayerRemoving:Connect(function(Player)
	local Table = TableValues(Player)
	local S, E = pcall(function()
		PlayerData:SetAsync(Player.UserId, Table)
	end)
	if S then
		print("DataStored")
	else
		warn(E)
	end
end)

That was how i saved it, but now i will show you how i get the data

local data = PlayerData:GetAsync(Player.UserId)
	if data ~= nil then
		Coins.Value = data["Coins"]
		Size.Value = data["Size"]
		TotalSize.Value = data["TotalSize"]
		Kills.Value = data["Kills"]
		MaxHealth.Value = data["MaxHealth"]
		SizeVal2.Value = data["SizeVal2"]
		CoinsVal2.Value = data["CoinsVal2"]
		Music.Value = data["Music"]
		SFX.Value = data["SFX"]
		Popups.Value = data["Popups"]
		Sell.Value = data["Sell"]
		Teleport.Value = data["Teleport"]
		MaxSizeDesc.Value = data["MaxSizeDesc"]
		Code1.Value = data["Code1"]
		Code2.Value = data["Code2"]
		Code3.Value = data["Code3"]
		Code4.Value = data["Code4"]
		Code5.Value = data["Code5"]
		Kid.Value = data["Kid"]
		Adult.Value = data["Adult"]
		Grandpa.Value = data["Grandpa"]
		Horse.Value = data["Horse"]
		Crocodile.Value = data["Crocodile"]
		Zebra.Value = data["Zebra"]
		Tiger.Value = data["Tiger"]
		Ostrich.Value = data["Ostrich"]
		Giraffe.Value = data["Giraffe"]
		Bear.Value = data["Bear"]
		Rhino.Value = data["Rhino"]
		GreatShark.Value = data["GreatShark"]
		Elephant.Value = data["Elephant"]
		TRex.Value = data["TRex"]
		Hydra.Value = data["Hydra"]
		Minotaur.Value = data["Minotaur"]
		Cyclops.Value = data["Cyclops"]
		Chimera.Value = data["Chimera"]
		Typhon.Value = data["Typhon"]
		KingKong.Value = data["KingKong"]
		Livyatan.Value = data["Livyatan"]
		Mosasaurus.Value = data["Mosasaurus"]
		Megalodon.Value = data["Megalodon"]
		BlueWhale.Value  = data["BlueWhale"]
		Kraken.Value = data["Kraken"]
		Leviathan.Value = data["Leviathan"]
		Dirt.Value = data["Dirt"]
		Ice.Value = data["Ice"]
		Sand.Value = data["Sand"]
		Grass.Value = data["Grass"]
		Aqua.Value = data["Aqua"]
		Cloud.Value = data["Cloud"]
		Liquid.Value = data["Liquid"]
		DNA.Value = data["DNA"]
		Tool.Value = data["Tool"]
		Rank.Value = data["Rank"]
		Stage2.Value = data["Stage 2"]
		Stage3.Value = data["Stage 3"]
		Stage4.Value = data["Stage 4"]
		Stage5.Value = data["Stage 5"]
		Stage6.Value = data["Stage 6"]
		Stage7.Value = data["Stage 7"]
		Stage8.Value = data["Stage 8"]
		Stage9.Value = data["Stage 9"]
		Stage10.Value = data["Stage 10"]
		Stage11.Value = data["Stage 11"]
		RebirthMultiplier.Value = data["RebirthMultiplier"]
		WalkSpeed.Value = data["WalkSpeed"]
		Concealed.Value = data["Concealed"]
		for i, v in pairs(ToolsOwned:GetChildren()) do
			v.Value = data[v.Name]
		end

I do have a backup save that does the same. but it didn’t really work as i still get dataloss in my game. I get about 500 players each day so idk if this is normal i do use datastore 1

3 Likes

What errors (if any) are returning?

Have you checked your basics, such as having datastores enabled?

Idk, i’ve never experienced errors, but my players have and how could i release a game without datastores enabled and not notice it

You need to enable them via game settings. (See images below)


If you have any other issues, or it begins returning errors, please let me know.

bro i told you it’s not that. Lmao why should a game with 100 active with datastores forget to turn em on? like bro i told you already it’s on. The game is storing alot of data, and it’s working it’s just some players experiencing dataloss

1 Like

Btw your script could be shortened to this:

local function TableValues(Player: Instance)
	
	local Player_stats = {}
	local foldersToSaveFrom = {Player.leaderstats, Player.ValuesFolder, Player.Settings, Player.Codes, Player.DnaOwned, Player.EquippedFolder, Player.RanksOwned, Player.ToolsOwned}
	
	for _, folder in foldersToSaveFrom do
		
		for _, value in folder:GetChildren() do
			
			Player_stats[value.Name] = value.Value
			
		end
		
	end

	return Player_stats
	
end

Was this happening previously or only after the ROBLOX update?

I read once that :SetAsync is known for data losses, I would suggest using :UpdateAsync although its a little slower thanks to it reading data too and returning it through an argument but might do the job.

Edit: I had a similar problem before too and UpdateAsync somehow fixed it

Possible fix 2: add a delay between joining and saving, since you use values and if the player leaves before the values are recognised it can save default value data aka 0s or empty strings

You could add a cooldown how long you need to be on the server for it to save, did it for 10 seconds in the game I’m making

Might be worth switching to datastore2 tbh, there’s never been a single report of dataloss when using that module

1 Like

Use UpdateAsync instead of SetAsync, it’s more reliable as it simply updates a player’s value instead of overwriting it completely, so it reduces the chance of data loss. I noticed in my previous project data-loss occurred and I was using SetAsync

ik but really don’t care as it does the same thing lol

1 Like

Oh wait so that makes it like if the data looses it get’s the data from the previous play? or previous successful save

the update async caused my script to error:

Unable to cast value to function was the warning

	if S then
		print("DataStored");
	else

This might fail if the datastore is working but the data failed to be accessed for the player, you should check the E value after a success because you could be wiping out player data under conditions where the datastore is working but the players data fails to be accessed.

The most common reason behind the data loses in a working DataStore script, is attempting to save values which haven’t been loaded yet.
The servers and data stores experience plenty of issues, delays etc. so in certain circumstances the PlayerRemoving event will be called before all the values have been set which usually results in saving nil or an empty table to the data store.

To prevent this, you can use simply use a variable to make sure the values have loaded successfully:

local isLoaded = {}

Players.PlayerAdded:Connect(function(player)
  -- load all the values here
  isLoaded[player] = true
end)

Players.PlayerRemoving:Connect(function(player)
  if (isLoaded[player]) then
    -- save the data here
  end
end)
1 Like

The way I use :UpdateAsync is like this

local s,e = pcall(function()
	DataStore:UpdateAsync(UserID, function(oldData)
		local PreviousData = oldData
		if PreviousData then
			-- has previous data
		else
			-- doesn't have previous data
		end
	end)
end)

The ‘s’ means that UpdateAsync() worked and the function successfully returned, i.e. it was able to access the datastore. The error condition will be set if the players data failed to load so you should always check the ‘e’ in case ‘s’ told you the DataStore is working, but the ‘e’ will tell you if the data did/didn’t load.

What I recommend is wrapping your GetAsync request in a pcall, as that will give you more freedom to handle errors rather than just checking if your data is nil or not. Datastores don’t always work correctly, so maybe your data loss stems from the fact that you’re not correctly handling the potential errors associated with the retrieval of your player’s data. You mentioned you had a backup system in place, so you could send that if you believe it may be the source of your problem.

Example:

local data
local success, err = pcall(function()
       data = yourDataStore:GetAsync(yourKey)
end)
if err then
    retry()
end
1 Like

Exactly what I was trying to say the success says the function worked, not if the data was able to be accessed, the error condition will tell you that.

1 Like

Yup, that success boolean can be deceiving sometimes…

1 Like