Datastore error. Why is this happening when there are no issues?

I’m having a throttle issue when there is nothing wrong.
Screenshot: Screenshot by Lightshot

Script:

local Scope = "Version1"

local DataStore = game:GetService("DataStoreService"):GetDataStore("Stats", Scope)
local Event = game:GetService("ReplicatedStorage"):FindFirstChild("Events"):FindFirstChild("DATASTORE_UPDATE")
local PlayerService = game:GetService("Players")
local Main_Folder = Instance.new("Folder")
Main_Folder.Name = "DataStore"
Main_Folder.Parent = game:GetService("ServerScriptService")

PlayerService.PlayerAdded:Connect(function(Player)
	local Folder = Instance.new("Configuration")
	Folder.Name = Player.Name
	Folder.Parent = Main_Folder
	
	local Wins_Folder = Instance.new("IntValue")
	Wins_Folder.Name = "Total Wins"
	Wins_Folder.Parent = Folder
	
	local Deaths_Folder = Instance.new("IntValue")
	Deaths_Folder.Name = "Total Deaths"
	Deaths_Folder.Parent = Folder
	
	local Best_Killstreak_Folder = Instance.new("IntValue")
	Best_Killstreak_Folder.Name = "Best Killstreak"
	Best_Killstreak_Folder.Parent = Folder
	
	local SSS = game:GetService("ServerScriptService")
	local Folder = SSS:FindFirstChild("DataStore")
	
	wait(3)
	
	--[[ > > > Loading stats < < < ]]--
	
	local succ, err = pcall(function()
		local Score = DataStore:GetAsync(Player.UserId) or {
			0,
			0,
			0
		}
		Wins_Folder.Value = Score["Total Wins"]
		Deaths_Folder.Value = Score["Total Deaths"]
		Best_Killstreak_Folder.Value = Score["Best Killstreak"]
	end)
	
	if succ then
		print("Loaded data for", Player.UserId)
	else
		print("Failed loading data for", Player.UserId, ":", err)
	end
	
	Event:FireClient(Player, Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Wins").Value, "WINS")
	Event:FireClient(Player, Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Deaths").Value, "DEATHS")
	Event:FireClient(Player, Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Best Killstreak").Value, "KILLSTREAK")
	
	--[[ > > > Update KD when player joins < < < ]]--
	
	local Update_Wins = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Wins")
	local Update_Deaths = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Deaths")
	local updatekd = Update_Wins.Value / (Update_Deaths.Value == 0 and 1 or Update_Deaths.Value)
	Event:FireClient(Player, math.floor(updatekd * 100 + 0.5) / 100, "K/D RATIO")

	--[[ > > > Get their stats < < < ]]--
	
	local Wins_Changed = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Wins")
	Wins_Changed:GetPropertyChangedSignal("Value"):Connect(function()
		Event:FireClient(Player, Wins_Changed.Value, "WINS")
		local Update = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Deaths").Value
		local kd = Update / (Wins_Changed.Value == 0 and 1 or Wins_Changed.Value)
		Event:FireClient(Player, math.floor(kd * 100 + 0.5) / 100, "K/D RATIO")
	end)
	
	local Deaths_Changed = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Deaths")
	Deaths_Changed:GetPropertyChangedSignal("Value"):Connect(function()
		Event:FireClient(Player, Deaths_Changed.Value, "DEATHS")
		local Update = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Wins").Value
		local kd = Update / (Deaths_Changed.Value == 0 and 1 or Deaths_Changed.Value)
		Event:FireClient(Player, math.floor(kd * 100 + 0.5) / 100, "K/D RATIO")
	end)
	
	local Best_Killstreak_Changed = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Best Killstreak")
	Best_Killstreak_Changed:GetPropertyChangedSignal("Value"):Connect(function()
		Event:FireClient(Player, Best_Killstreak_Changed.Value, "KILLSTREAK")	
	end)
	
	--[[ > > > Save when player leaves < < < ]]--
	
	PlayerService.PlayerRemoving:Connect(function(Player)
		if game:GetService("RunService"):IsStudio() then
        	return
		end
		local succ1, err1 = pcall(function()
			DataStore:SetAsync(Player.UserId, {
				["Total Wins"] 			= Wins_Folder.Value,
				["Total Deaths"] 		= Deaths_Folder.Value,
				["Best Killstreak"]		= Best_Killstreak_Folder.Value
			})
		end)
		if succ1 then
			print("[PlayerRemoving] Saved data for", Player.Name)
		else
			print("[PlayerRemoving] Could not save data for", Player.Name .. ".", err1)
		end	
	end)
	
	--[[ > > > Save if shutdown occurs < < < ]]--
		
	game:BindToClose(function()
		if game:GetService("RunService"):IsStudio() then
        	return
		end
		wait(3)
		for _,v in pairs(PlayerService:GetPlayers()) do
			local succ2, err2 = pcall(function()
				DataStore:SetAsync(v.UserId, {
					["Total Wins"] 			= Wins_Folder.Value,
					["Total Deaths"] 		= Deaths_Folder.Value,
					["Best Killstreak"]		= Best_Killstreak_Folder.Value
				})
			end)
			if succ2 then
				print("[BindToClose] Saved data for", v.Name)
			else
				print("[BindToClose] Could not save data for", v.Name .. ".", err2)
			end	
		end
	end)

There doesn’t seem to be any issues with your data store code, at least any that cause throttling issues. You only call GetAsync when they join and SetAsync on leave and when the server shuts down.
Therefore, there must be something else causing throttle issues, though I wouldn’t know what it would be.


Source: Data Stores

Unless:

  • you are joining and leaving your game twice in 6 seconds, then it would be from SetAsync requests,
  • or you are joining and leaving the same server at least 70 times a minute, which is very hard to do,
  • or you have another script that handles data stores,

I don’t know what could be causing this.

  1. Isn’t it kinda impossible to do your first statement?
  2. That is truly impossible.
  3. I do not have any other scripts dealing with datastore (except Kohl’s admin, not sure how that one work.)

Either way, this does NOT make sense at all for me.

1 Like

The first one is possible if you click play while already in the game and if you have a fast internet connection. The second is basically an edge case that is impossible for any valid player of your game to do, so you might as well ignore that.

What request is it that is being warned about? Is it the save request?

Try disabling Kohl’s admin temporarily and see if the issue persists. Many admin scripts include the use of data saving in games. If you can, search through the admin script and check if any DataStore calls are being made. Let us know what happens.

It can’t be the save request as it warned me after I loaded their data.

I believe it is Kohl’s admin as I did not have any issues with 8 players in studio. But then I’ll have to remove the permanent ban function sadly if so.

Try disabling it and see what happens. You can have a go at making your own banning system too, if you like :wink:

True, but either way I’d have to include the GetAsync() (which seems to be the problem here?). As Kohl’s admin wouldn’t use anything else than GetAsync once a player join. Right?

Kohl’s is heavily outdated, you should use Adonis (same owner)

If you code your own ban system you have more control over how it is done by including trello lists for one and making sure it isn’t going over any rate limits.

Kohl’s admin is not really outdated as he has made a new one which works, but if it interrupts with my game functions I’ll simply remove it.

1 Like

If you’re concerned about making GetAsync requests, you can always use the same request and include a value in the data to identify if a player is banned. This would only benefit you at this point.

Caught your error.

The PlayerRemoving event and BindToClose constantly looped as you incorrectly ended the PlayerAdded event. This meant that every time a player joined, the script would run a new BindToClose and a PlayerRemoving connection. Simple mistakes can lead to drastic effects. This resulted in many SetAsync requests being called every time after a player left.

I’ve cleaned your code up and made a few changes for it to properly run. Let me know if it works.

local Scope = "Version1"

local DataStore = game:GetService("DataStoreService"):GetDataStore("Stats", Scope)
local Event = game:GetService("ReplicatedStorage"):FindFirstChild("Events"):FindFirstChild("DATASTORE_UPDATE")
local PlayerService = game:GetService("Players")
local Main_Folder = Instance.new("Folder")
Main_Folder.Name = "DataStore"
Main_Folder.Parent = game:GetService("ServerScriptService")

PlayerService.PlayerAdded:Connect(function(Player)
	local Folder = Instance.new("Configuration")
	Folder.Name = Player.Name
	Folder.Parent = Main_Folder
	
	local Wins_Folder = Instance.new("IntValue")
	Wins_Folder.Name = "Total Wins"
	Wins_Folder.Parent = Folder
	
	local Deaths_Folder = Instance.new("IntValue")
	Deaths_Folder.Name = "Total Deaths"
	Deaths_Folder.Parent = Folder
	
	local Best_Killstreak_Folder = Instance.new("IntValue")
	Best_Killstreak_Folder.Name = "Best Killstreak"
	Best_Killstreak_Folder.Parent = Folder
	
	local SSS = game:GetService("ServerScriptService")
	local Folder = SSS:FindFirstChild("DataStore")
	
	wait(3)
	
	--[[ > > > Loading stats < < < ]]--
	
	local succ, err = pcall(function()
		local Score = DataStore:GetAsync(Player.UserId) or {
			0,
			0,
			0
		}
		Wins_Folder.Value = Score["Total Wins"]
		Deaths_Folder.Value = Score["Total Deaths"]
		Best_Killstreak_Folder.Value = Score["Best Killstreak"]
	end)
	
	if succ then
		print("Loaded data for", Player.UserId)
	else
		print("Failed loading data for", Player.UserId, ":", err)
	end
	
	Event:FireClient(Player, Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Wins").Value, "WINS")
	Event:FireClient(Player, Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Deaths").Value, "DEATHS")
	Event:FireClient(Player, Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Best Killstreak").Value, "KILLSTREAK")
	
	--[[ > > > Update KD when player joins < < < ]]--
	
	local Update_Wins = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Wins")
	local Update_Deaths = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Deaths")
	local updatekd = Update_Wins.Value / (Update_Deaths.Value == 0 and 1 or Update_Deaths.Value)
	Event:FireClient(Player, math.floor(updatekd * 100 + 0.5) / 100, "K/D RATIO")

	--[[ > > > Get their stats < < < ]]--
	
	local Wins_Changed = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Wins")
	Wins_Changed:GetPropertyChangedSignal("Value"):Connect(function()
		Event:FireClient(Player, Wins_Changed.Value, "WINS")
		local Update = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Deaths").Value
		local kd = Update / (Wins_Changed.Value == 0 and 1 or Wins_Changed.Value)
		Event:FireClient(Player, math.floor(kd * 100 + 0.5) / 100, "K/D RATIO")
	end)
	
	local Deaths_Changed = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Deaths")
	Deaths_Changed:GetPropertyChangedSignal("Value"):Connect(function()
		Event:FireClient(Player, Deaths_Changed.Value, "DEATHS")
		local Update = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Total Wins").Value
		local kd = Update / (Deaths_Changed.Value == 0 and 1 or Deaths_Changed.Value)
		Event:FireClient(Player, math.floor(kd * 100 + 0.5) / 100, "K/D RATIO")
	end)
	
	local Best_Killstreak_Changed = Main_Folder:FindFirstChild(Player.Name):FindFirstChild("Best Killstreak")
	Best_Killstreak_Changed:GetPropertyChangedSignal("Value"):Connect(function()
		Event:FireClient(Player, Best_Killstreak_Changed.Value, "KILLSTREAK")	
	end)

end)
	
--[[ > > > Save when player leaves < < < ]]--

PlayerService.PlayerRemoving:Connect(function(Player)
	if game:GetService("RunService"):IsStudio() then
    	return
	end
	local succ1, err1 = pcall(function()
		local Wins_Folder = Main_Folder:WaitForChild(Player.Name)["Total Wins"]
		local Deaths_Folder = Main_Folder:WaitForChild(Player.Name)["Total Deaths"]
		local Best_Killstreak_Folder = Main_Folder:WaitForChild(Player.Name)["Best Killstreak"]
		DataStore:SetAsync(Player.UserId, {
			["Total Wins"] 			= Wins_Folder.Value,
			["Total Deaths"] 		= Deaths_Folder.Value,
			["Best Killstreak"]		= Best_Killstreak_Folder.Value
		})
	end)
	if succ1 then
		print("[PlayerRemoving] Saved data for", Player.Name)
	else
		print("[PlayerRemoving] Could not save data for", Player.Name .. ".", err1)
	end	
end)

--[[ > > > Save if shutdown occurs < < < ]]--
	
game:BindToClose(function()
	if game:GetService("RunService"):IsStudio() then
    	return
	end
	wait(3)
	for _,v in pairs(PlayerService:GetPlayers()) do
		local succ2, err2 = pcall(function()
			local Wins_Folder = Main_Folder:WaitForChild(v.Name)["Total Wins"]
			local Deaths_Folder = Main_Folder:WaitForChild(v.Name)["Total Deaths"]
			local Best_Killstreak_Folder = Main_Folder:WaitForChild(v.Name)["Best Killstreak"]

			DataStore:SetAsync(v.UserId, {
				["Total Wins"] 			= Wins_Folder.Value,
				["Total Deaths"] 		= Deaths_Folder.Value,
				["Best Killstreak"]		= Best_Killstreak_Folder.Value
			})
		end)
		if succ2 then
			print("[BindToClose] Saved data for", v.Name)
		else
			print("[BindToClose] Could not save data for", v.Name .. ".", err2)
		end	
	end
end)

I don’t see any difference. What was it?

You should not be getting throttle requests anymore. The issue was that for every player that joined, new threads were being recreated.

Example? I dont see any changes that’s noticeable

Even though the code might be fixed, I would recommend handling datastore error cases so that the datastore tries to re-save the data after a failed attempt. Simply printing the output is good for debugging, but it won’t resolve unhappy users that lost data after a purchase via robux. Just a thought :slight_smile:

What do you mean though. I’m doing that

You are not doing that. The only time the server attempts to save player data is when the player is leaving, or when the game is closing.

Don’t see why I need a loop to save etc, my way is the best?