Adding new value to Playerdata script results in data loss. How would I prevent this?

Hello, I followed this YouTube tutorial by Tech with Mike on how to save and load multiple sets of data with Data Store. The script works perfectly, although I found one small (BIG) issue: Adding or removing values from the script results in complete data loss. How would I fix/prevent this??

Here is my full script:

local DSS = game:GetService("DataStoreService")
local playerData = DSS:GetDataStore("PlayerData")

local function onPlayerJoin(player)
	
	-- Levels \/
	local leaderstats = Instance.new("Folder",player)
	leaderstats.Name = "leaderstats"

	local level = Instance.new("NumberValue",leaderstats)
	level.Name = "Level"
	level.Value = 1

	local xp = Instance.new("NumberValue",player)
	xp.Name = "xp"
	xp.Value = 0

	local requiredXp = Instance.new("NumberValue",player)
	requiredXp.Name = "requiredXp"
	requiredXp.Value = 250
	-- Levels /\

	--

	-- Currency \/
	local gold = Instance.new("NumberValue",player)
	gold.Name = "gold"
	gold.Value = 100

	local gems = Instance.new("NumberValue",player)
	gems.Name = "gems"
	gems.Value = 50
	-- Currency /\

	--

	-- Hidden player stats \/
	local damage = Instance.new("NumberValue",player)
	damage.Name = "damage"
	damage.Value = 0

	local kills = Instance.new("NumberValue",player)
	kills.Name = "kills"
	kills.Value = 0
	
	local dungeonsCompleted = Instance.new("NumberValue",player)
	dungeonsCompleted.Name = "dungeonsCompleted"
	dungeonsCompleted.Value = 0
	-- Hidden player stats /\

	--

	-- Skill Points \/
	local pointsToSpend = Instance.new("NumberValue",player)
	pointsToSpend.Name = "pointsToSpend"
	pointsToSpend.Value = 2

	local swordPoints = Instance.new("NumberValue",player)
	swordPoints.Name = "swordPoints"
	swordPoints.Value = 0

	local aspectPoints = Instance.new("NumberValue",player)
	aspectPoints.Name = "aspectPoints"
	aspectPoints.Value = 0

	local healthPoints = Instance.new("NumberValue",player)
	healthPoints.Name = "healthPoints"
	healthPoints.Value = 0
	-- Skill Points /\
	
	-- Holdables \/
	
	
	
	-- Holdables /\
	
	local playerUserId = "Player_"..player.UserId
	local data = playerData:GetAsync(playerUserId)
	if data then
		level.Value = data["Level"]
		xp.Value = data["xp"]
		requiredXp.Value = data["requiredXp"]
		
		gold.Value = data["gold"]
		gems.Value = data["gems"]
		
		damage.Value = data["damage"]
		kills.Value = data["kills"]
		dungeonsCompleted.Value = data["dungeonsCompleted"]
		
		pointsToSpend.Value = data["pointsToSpend"]
		swordPoints.Value = data["swordPoints"]
		aspectPoints.Value = data["aspectPoints"]
		healthPoints.Value = data["healthPoints"]
	else
		level.Value = 1
		xp.Value = 0
		requiredXp.Value = 250
		
		gold.Value = 100
		gems.Value = 50
		
		damage.Value = 0
		kills.Value = 0
		dungeonsCompleted.Value = 0
		
		pointsToSpend.Value = 2
		swordPoints.Value = 0
		aspectPoints.Value = 0
		healthPoints.Value = 0
	end
	
	-- Level Up and XP \/
	xp.Changed:Connect(function()
		if xp.Value >= requiredXp.Value then
			
			player.Character:WaitForChild("Humanoid").Health = player.Character:WaitForChild("Humanoid").MaxHealth
			
			xp.Value -= requiredXp.Value

			level.Value += 1

			requiredXp.Value *= 1.10

			pointsToSpend.Value += 2

			local levelUpSFX = game.ReplicatedStorage.Sounds.Player.LevelUpSound:Clone()

			levelUpSFX.Parent = player.Character
			levelUpSFX:Play()

			levelUpSFX.Ended:Wait()

			levelUpSFX:Destroy()

		end
	end)
	-- Level Up & XP /\
	
end

local function create_table(player)
	local player_stats = {}
	for _,stat in pairs(player:GetDescendants()) do
		if stat:IsA("NumberValue") or stat:IsA("IntValue") then
			player_stats[stat.Name] = stat.Value
		end
	end
	return player_stats
end

local function onPlayerExit(player)
	local player_stats = create_table(player)
	local success, err = pcall(function()
		local playerUserId = "Player_"..player.UserId
		playerData:SetAsync(playerUserId, player_stats)
	end)
	
	if not success then
		warn("Could not save data", err)
	end
	
end

game.Players.PlayerAdded:Connect(onPlayerJoin)

game.Players.PlayerRemoving:Connect(onPlayerExit)

Any and all help is appreciated, thank you!

EDIT: It prints this error

value of type nil cannot be converted to a number

and it links to the new value under the “GetAsync - if data then” section.
i.e. new.Value = data[“new”]

What line number is the error occuring on?

I just edited the original post to include it, sorry about that!

It seems to be saying that data[“Level”] is nil, or that one of the other values below it are nil.

If you try adding or DEFAULTVALUE after each of them, where DEFAULTVALUE is, well, the default value, does it resolve the issue?

e.g.

level.Value = data["Level"] or 1
xp.Value = data["xp"] or 0
requiredXp.Value = data["requiredXp"] or 250
1 Like

That worked, thank you so much! It also turns out that I glanced over the “else” statement, forgetting that I need to add the new value to that as well. I’m still fairly new to scripting, so I appreciate you helping me out and not making fun of me because of such a silly mistake. Thank you again!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.