Help with datastores

  1. What do you want to achieve?
    I am trying to fix my game datastore.

  2. What is the issue?
    The datastores one day got corrupt for me and all other games(even ones that i have no direct association with) that use the same datastore script. The problem seems to happen randomly for players, and its very unpredictable on if it will happen to you next or not. It will fail to load the datastore then show your data in the blurred-out kicked screen.

  3. What solutions have you tried so far?
    I have tried to fix it by simply removing the part of the script that kicks you, leaving you with just your stats but it felt VERY insecure and there have been reports of total data loss.
    I also tried to use datastore2 but i have no idea how it works and i would have to take the (presumably) corrupted datastores and move it to datastore2.

Here is the script. This script is for a Slap Battles fangame that I own.

local DS = game:GetService("DataStoreService"):GetDataStore("SaveKills")
local sessionData = {}


game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder",player)	
	leaderstats.Name = "leaderstats"

	local Slaps = Instance.new("IntValue",leaderstats)
	Slaps.Name = "Kills" 




	local Glove = Instance.new("StringValue",leaderstats)
	Glove.Name = "Glove"
	Glove.Value = "Killstreak"



	local success = nil
	local playerData = nil
	local attempt = 1

	repeat
		success, playerData = pcall(function()
			return DS:GetAsync(player.UserId, sessionData[player.UserId]) -- getting plr data
		end)

		attempt += 1
		if not success then
			warn(playerData)
			task.wait(3)
		end
	until success or attempt == 5 -- if data fails to load, it will try again for 5 times.

	if success then
		if not playerData then -- checking if the player has never played
			playerData = {
				["Kills"] = 0 -- How many slaps the player should have upon joining for the first time
			}
		end
		sessionData[player.UserId] = playerData
	else
		Slaps.Value = sessionData[player.UserId].Kills
		task.wait(3)
		if Slaps.Value~=0 and Slaps.Value~=nil then
		else
			player:Kick("Unable to load your data, please try again.") -- Kicks player if data fails to load
		end
	end

	Slaps.Value = sessionData[player.UserId].Kills

	Slaps.Changed:Connect(function()
		sessionData[player.UserId].Kills = Slaps.Value
	end)
end)

function playerLeaving(plr)
	if sessionData[plr.UserId] then
		local success = nil
		local errorMsg = nil
		local attempt = 1

		repeat
			success, errorMsg = pcall(function()
				if game.PrivateServerId ~= "" then

				else
					DS:SetAsync(plr.UserId, sessionData[plr.UserId]) -- saves data upon leaving
				end

			end)

			attempt += 1
			if not success then
				warn(errorMsg)
				task.wait(3)

			end
		until success or attempt == 5 -- If data fails to save, it will try again for 5 times.

		if success then
			print("Data saved for "..plr.UserId)
		else
			warn("Unable to save data for "..plr.UserId)
		end
	end
end

game.Players.PlayerRemoving:Connect(playerLeaving, game.Players.PlayerRemoving)

local RunService = game:GetService("RunService")

function serverShutdown()  -- Runs if server is forcefully shut down
	if RunService:IsStudio() then -- doesn't run function if in studio
		return
	end

	for i, plr in ipairs(game.Players:GetChildren()) do
		task.spawn(function()
			playerLeaving(plr)
		end)
	end
end

also note that it for some reason doesnt kick you in a private server, or the first time you join after the game updates. This makes it very confusing and hard to identify the problem.

This should be in #help-and-feedback:scripting-support

You’re using pcalls incorrectly. playerData is actually an errormessage not the data it got from GetAsync. By the way GetAsync only needs 1 value, which is the player’s UserId, else it will most likely give an error of Unable to cast value to Object

You should set the data to a variable outside the pcall and access it from there
Example:

local playerData
success, errorMessage = pcall(function()
playerData = DS:GetAsync(player.UserId) -- data is now in playerData
end)

attempt += 1
if not success then
warn(errorMessage)
task.wait(3)
end

The person above is correct by the way.

thank you, but i still dont understand

the datastores have been working perfectly fine for months beforehand. It only recently started to have issues with all the games that use this script, so i believe this is a roblox issue. But i dont understand how i could have been using pcall wrong, when it has been working for up to a year now.

Maybe you forgot that you edited it and deleted some lines