Error: value of type nil cannot be converted to a number

So i know this error but i do not know why is showing it?

So What i am trying to do is save a int value (yes i tried number values it does not work ) So heres the part of the script that gives the error:


--The script is in server script

TUV.Value = sessionData[player.UserId].TUV

heres the parent of that part:

local Players = game:GetService("Players")
local RS = game:GetService("GeometryService")
local DSS = game:GetService("DataStoreService")

local database = DSS:GetDataStore("data")
local sessionData = {}

function PlayerAdded(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	
	local Money = Instance.new("IntValue")
	Money.Name = "Money"
	Money.Parent = leaderstats
	
	local TUV = game.Workspace:WaitForChild("Upgrades"):WaitForChild("TestUpgradeValue")
	
	local success = nil
	local playerData = nil
	local attempt = 1
	
	repeat
		success, playerData = pcall(function()
			return database:GetAsync(player.UserId)
		end)

		attempt += 1
		if not success then
			warn(playerData)
			task.wait(3)
		end
	until success or attempt == 5

	if success then
		print("Connected to database")
	if not playerData then
		print("Assigning default data")
		playerData = {
			["Money"] = 0 ,
			["TUV"] = 0
					}
		end
		sessionData[player.UserId] = playerData
	else
		warn("Unable to get data for ", player.UserId)
		player:Kick("Unable to load your data. Try again later")
	end
	
	Money.Value = sessionData[player.UserId].Money
	
	TUV.Value = sessionData[player.UserId].TUV
	
	Money.Changed:Connect(function()
		sessionData[player.UserId].Money = Money.Value
	end)
	
	TUV.Changed:Connect(function()
		sessionData[player.UserId].TUV = TUV.Value
	end)
	
	leaderstats.Parent = player
end
Players.PlayerAdded:Connect(PlayerAdded)

Is there anyway to fix this? And if you know the reason can you tell me the problem just in case if this happens in the future

By any chance did you run the game before adding ‘TUV’ to your datastore? If so, when it saved there would not be a TUV value in the save data, so every time you enter the game it loads your savedata as:

playerData = {
	["Money"] = 0 
}

Then when it tries to set the TUV.Value later, it’s attempting to set it to nil.

You can double check by printing ‘playerData’ after it loads and ensuring it’s correct.

1 Like

You’re only setting sessionData[player.UserId]'s value if playerData is nil, you’re not setting it if playerData already exists

1 Like

Well spotted, that looks like the issue.

Moving sessionData[player.UserId] = playerData to just above where you set Money.Value should fix it.

2 Likes

Unfortunately I made a mistake, they are setting its value outside of the if statement so it should also be set if playerData exists, the code’s formatting confused me :sweat_smile:


@iuseselfnone

Does the code error only for TUV’s value, not for Money?

1 Like

:joy: :joy: :joy: Damn, caught me off-guard as well.

Reformatted for everyone’s benefit:

if success then
	print("Connected to database")
	if not playerData then
		print("Assigning default data")
		playerData = {
			["Money"] = 0 ,
			["TUV"] = 0
		}
	end
	sessionData[player.UserId] = playerData
else
	warn("Unable to get data for ", player.UserId)
	player:Kick("Unable to load your data. Try again later")
end
2 Likes

One of the references to ‘TUV’ is nil, it doesn’t exist. It’s either to the left or to the right. Check the Instance scoped left-side TUV and it’s Value. Then check the right-side; firstly the sessionData indexed by player.UserId and then the reference to that data named TUV.

1 Like

Just to add on to what myself and @dduck5tar suggested, and if it’s the datastore not containing the TUV value. Something like this:

local defaultPlayerData = {
	['Money'] = 0;
	['TUV'] = 0;
}

local PlayerAdded(player)
	-- Make leaderstats
	
	local success = nil
	local playerData = nil
	local attempt = 1

	repeat
		success, playerData = pcall(function()
			return database:GetAsync(player.UserId)
		end)

		attempt += 1
		if not success then
			warn(playerData)
			task.wait(3)
		end
	until success or attempt == 5

	if success then
		if not playerData then
			playerData = defaultPlayerData
		else
			for Index,Value in pairs(defaultPlayerData) do
				if not playerData[Index] then
					playerData[Index] = Value
				end
			end
		end
		sessionData[player.UserId] = playerData
		print("Connected to database")
	else
		warn("Unable to get data for ", player.UserId)
		player:Kick("Unable to load your data. Try again later")
		return;
	end

	-- Set all the values
	-- Bind all the .Changed events
end

…Should allow you the same functionality, while also future-proofing so that if you ever add extra variables to the default save data, players who had played prior to that change will automatically get updated to the newest format when they join.

1 Like

I went ahead an rewrote the script:

local DSS = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local RS = game:GetService("GeometryService")
local Workspace = game:GetService("Workspace")

local database = DSS:GetDataStore("data")
local TUV = Workspace:WaitForChild("Upgrades"):WaitForChild("TestUpgradeValue")

local sessionData = {}

local function GetPlayerData(player)
	local attempt = 1

	while attempt < 5 do
		local success, playerData = pcall(database.GetAsync, database, player.UserId)

		if success then
			return playerData
		else
			attempt += 1
			task.wait(3)
		end
	end

	warn(`Failed to get PlayerData for Player {player.UserId} ({player.DisplayName})`)
end

local function PlayerAdded(player)
	local playerData = GetPlayerData(player)

	if playerData == nil then
		warn(`PlayerData for Player {player.UserId} ({player.DisplayName}) is nil, continuing using default values`)

		playerData = {
			Money = 0,
			TUV = 0
		}
	end

	sessionData[player.UserId] = playerData

	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local Money = Instance.new("IntValue")
	Money.Name = "Money"
	Money.Value = playerData.Money
	Money.Parent = leaderstats

	TUV.Value = playerData.TUV

	Money.Changed:Connect(function(value)
		sessionData[player.UserId].Money = value
	end)

	TUV.Changed:Connect(function(value)
		sessionData[player.UserId].TUV = value
	end)
end

Players.PlayerAdded:Connect(PlayerAdded)

I’ve kept the same naming scheme, and it should work like the original, but hopefully without any issues

If it doesn’t work, then @dduck5tar and @darkelementallord are correct in suggesting that the issue lies in how the player data is being saved

2 Likes

Hello sorry for the VERY VERY late response but I had to go somewhere, You guys helped me alot and it actually works now! Thank you all for helping!