Value of type nil cannot be converted to a number error

I recently made a leaderstats datastore, but it consistently prints out an error message saying “value of type nil cannot be converted to a number” when I hop in a test session with 2 or more players. Can somebody tell me what the bug could be or what I’m doing wrong?

local deathdata, killdata, windata
	local success, errormessage = pcall(function()
		deathdata = ds:GetAsync("Deaths-"..player.UserId)
		killdata = ds:GetAsync("Kills-"..player.UserId)
		windata = ds:GetAsync("Wins-"..player.UserId)
	end)
	
	if success then
		Deaths.Value = deathdata
		Kills.Value = killdata
		Wins.Value = windata
	end

game.Players.PlayerRemoving:Connect(function(player)
	local success, errormessage = pcall(function()
		ds:SetAsync("Deaths-"..player.UserId,player:WaitForChild("leaderstats"):WaitForChild("Deaths"):WaitForChild("Value"))
		ds:SetAsync("Kills-"..player.UserId,player:WaitForChild("leaderstats"):WaitForChild("Kills"):WaitForChild("Value"))
		ds:SetAsync("Wins-"..player.UserId,player:WaitForChild("leaderstats"):WaitForChild("Wins"):WaitForChild("Value"))
	end)
end)

I only pasted the section of the script I put leaderstats in

1 Like

Which line in particular is erroring?
Have you connected up a PlayerAdded event (you’d be surprised…)?

1 Like

Only the lines where it says

Deaths.Value = deathdata
Kills.Value = killdata
Wins.Value = windata

And yes, I have a playeradded linked to it, the script is written correctly I just didn’t paste the full thing since it’s quite lengthy and irrelevant to the issue.

1 Like

Let’s first dive into the error meaning. “Value of type nil” means that the instance you are trying to change is nil (doesn’t exist).

Given from where the error is occurring:

Your problem is the “Deaths” (and most likely), “Kills”, + “Wins” variables are not defined. Where do you define these variables?

Ill just paste the entire leaderstat script

local DataStoreService = game:GetService("DataStoreService")
local ds = DataStoreService:GetDataStore("DataStoreTest")

local RS = game:GetService("ReplicatedStorage")
local PlayerInventory = DataStoreService:GetDataStore("PlayerInventory")
local PlayerDeaths = DataStoreService:GetDataStore("PlayerInventory", "Coins")

local Players = game:GetService("Players")
local MarketPlaceService = game:GetService("MarketplaceService")

Players.PlayerAdded:Connect(function(player)	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	local Kills = Instance.new("IntValue")
	Kills.Name = "Kills"
	Kills.Parent = leaderstats
	Kills.Value = 0
	
	local Deaths = Instance.new("IntValue")
	Deaths.Name = "Deaths"
	Deaths.Parent = leaderstats
	Deaths.Value = 0
	
	local Wins = Instance.new("IntValue")
	Wins.Name = "Wins"
	Wins.Parent = leaderstats
	Wins.Value = 0
	
	player.CharacterAdded:Connect(function(char)
		local humanoid
		repeat
			humanoid = char:FindFirstChild("Humanoid")
			wait()
		until humanoid
		humanoid.Died:connect(function() 
			Deaths.Value = Deaths.Value + 1 
		end)
	end)
	
	player.CharacterAdded:Connect(function()
		local Humanoid = player.Character:WaitForChild("Humanoid")
		Humanoid.Died:Connect(function()
			local DamageDealer = Humanoid:FindFirstChild("creator")
			if DamageDealer and DamageDealer.Value then
				local Killer = game.Players:FindFirstChild(DamageDealer.Value.Name)
				if Killer and Killer.leaderstats then
					local kills = Killer.leaderstats:FindFirstChild("Kills")
					if kills then 
						kills.Value = (kills.Value or 0) + 1
					end
				end
			end
		end)
	end)
	
	local deathdata, killdata, windata
	local success, errormessage = pcall(function()
		deathdata = ds:GetAsync("Deaths-"..player.UserId)
		killdata = ds:GetAsync("Kills-"..player.UserId)
		windata = ds:GetAsync("Wins-"..player.UserId)
	end)
	
	if success then
		Deaths.Value = deathdata
		Kills.Value = killdata
		Wins.Value = windata
	end
	
	
end)

game.Players.PlayerRemoving:Connect(function(player)
	local success, errormessage = pcall(function()
		ds:SetAsync("Deaths-"..player.UserId,player:WaitForChild("leaderstats"):WaitForChild("Deaths"):WaitForChild("Value"))
		ds:SetAsync("Kills-"..player.UserId,player:WaitForChild("leaderstats"):WaitForChild("Kills"):WaitForChild("Value"))
		ds:SetAsync("Wins-"..player.UserId,player:WaitForChild("leaderstats"):WaitForChild("Wins"):WaitForChild("Value"))
	end)
end)

Took me a bit of testing to figure out what was going on, but it was actually the way you saved your data. I had the errors the other way around, your data was nil not the death, kills, and win instances.

use .Value not :WaitForChild("Value") since it is an attribute of the instance. WaitForChild() is meant for pausing code to wait for an instance to load into the game.

Btw, you also shouldn’t need to really use WaitForChild() regardless since you’ve already loaded in their data when they first joined the game.

The original script didn’t have waitforchild, I implemented that as an attempt to fix the issue. Leaderstats works fine and saves fine when I run test in studio and ingame. It starts showing the nil value error after I start running studio sessions with multiple instances. Why is that?

The error is happening because deathdata and the other variables are nil. The problem lies in the code assuming that a successful data load means there is data to be read. Success might be true even though there is no data, which is causing the variables to be nil. You have to implement a system which checks if the data loaded is nil. As easy way to do it is as follows:

local deathdata, killdata, windata
local success, errormessage = pcall(function()
	deathdata = ds:GetAsync("Deaths-"..player.UserId) or 0
	killdata = ds:GetAsync("Kills-"..player.UserId) or 0
	windata = ds:GetAsync("Wins-"..player.UserId) or 0
end)

The or 0 will set the value of the variable to 0 incase the value returned from the GetAsync function is nil. This ensures there is a default value.

When there is no data set in the datastore it will return nil.

if success then
	if deathdata and killdata and windata then
        Deaths.Value = deathdata
	    Kills.Value = killdata
	    Wins.Value = windata
    end
end

Also when a player leaves all their children gets deleted so getting the leaderstats and then also a value inside of that might not work.

Well the WaitForChild() is unnecessary and like I said only works to search for child instances (see documentation here). I ran the same code in studio (using .Value and not WaitForChild("Value")) and the code worked fine. You might be still receiving the error cause your values are still being saved as nil or haven’t been overwritten (if there is one player left, I recommend using game:BindToClose(), so the game saves the data before your server gets shut down).

Try using print() statements for the data when you retrieve it as well as before you save it to see if you are saving and retrieving proper values.

This seemed to do it! Now it sets it to 0 instead of returning nil ty!

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