Attempt to index nil with 'Value'

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? I am making a DataStore Script that, obviously, saves your data, but I’m having issues with it.

  2. What is the issue? Attempt to index nil with 'Value', apparently.

  3. What solutions have you tried so far? I’ve looked on the dev forum but nothing answered my question, nor helped.

Image of the error. :slight_smile:

The entire script of DatastoreManagerV2. (Server)

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local subtitleRemote = game.ReplicatedStorage.Client.Handlers.Gui.Subtitle

local dataStore = DataStoreService:GetDataStore("MainDataTable")
local default = {
	SessionLock    = false,
	XP             = 0,
	Wins           = 0,
	Level          = 0,
	Losses         = 0,
	TotalXP        = 0,
	TotalPlays     = 0,
}
local updateAsync = Enum.DataStoreRequestType.UpdateAsync

local function waitForRequestBudget()
	local currentBudget = DataStoreService:GetRequestBudgetForRequestType(updateAsync)

	while currentBudget < 1 do
		currentBudget = DataStoreService:GetRequestBudgetForRequestType(updateAsync)
		task.wait(5)
	end
end

local function setUp(player)
	local name = player.Name
	local userId = player.UserId
	local key = "Player_" .. userId

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

	local xp = Instance.new("IntValue")
	local level = Instance.new("IntValue")
	local wins = Instance.new("IntValue")
	local losses = Instance.new("IntValue")
	local totalXP = Instance.new("IntValue")
	local totalPlays = Instance.new("IntValue")
	
	xp.Name = "XP"
	wins.Name = "Wins"
	level.Name = "Level"
	losses.Name = "Losses"
	totalXP.Name = "Total XP"
	totalPlays.Name = "Total Matches Played"

	repeat task.wait() until player:GetAttribute("Tries")

	local tries = 7
	local firstTry = true
	
	player:SetAttribute("Tries", tries)
	
	local success, data, shouldWait
	
	repeat
		if tries > 0 then
			if not firstTry then
			
				tries -= 1
				
				player:SetAttribute("Tries", tries)
			
			end
		else
			break
		end
		
		if firstTry then
			firstTry = false
		end
		
		waitForRequestBudget()
		success = pcall(dataStore.UpdateAsync, dataStore, key, function(oldData)
			oldData = oldData or default
			if oldData.SessionLock then
				--He is still sessionlocked, so just wait
				if os.time() - oldData.SessionLock < 1800 then
					--session is alive
					shouldWait = true
				else
					--session is dead, take over
					oldData.SessionLock = os.time()
					data = oldData
					return data
				end
			else
				oldData.SessionLock = os.time()
				data = oldData
				return data
			end
		end)

		if shouldWait then
			task.wait(5)
			shouldWait = false
		end
	until (success and data) or not Players:FindFirstChild(name)
	if success and data then
		wins.Value = data.Wins or 0
		losses.Value = data.Losses or 0
		level.Value = data.Level or 0
		xp.Value = data.XP or 0
		totalXP.Value = data.TotalXP or 0
		totalPlays.Value = data.TotalPlays or 0
		
		print(string.format("got data (%s)", name))
		
		subtitleRemote:FireClient(player, "Remember to take screenshots of your data all the time, incase a data loss happens!", 6)
		
	else --By how the data didn't load, we'll assume it's a new player
		
		wins.Value = 0 or default.Wins
		losses.Value = 0 or default.Losses
		level.Value = 0 or default.Level
		xp.Value = 0 or default.XP
		totalXP.Value = 0 or default.TotalXP
		totalPlays.Value = 0 or default.TotalPlays
		
		print(string.format("data failed to load for %s, so it's probably a new player", player.Name))
		subtitleRemote:FireClient(player, "Your data has failed to load, you might be a new player", 6)
		
		task.delay(1.5, function()
			subtitleRemote:FireClient(player, "If you did have data..", 6)
			
			task.wait(0.8)
			
			subtitleRemote:FireClient(player, "Rejoin the game, make sure \"Save data on leave\" is disabled.", 6)
			
			task.wait(1.5)
			
			subtitleRemote:FireClient(player, "If you lost your data, contact a developer to gain your data back.", 6)
			
			task.wait(1)
			
			subtitleRemote:FireClient(player, "Remember to take screenshots of your data all the time, incase a data loss happens!", 6)
		end)
	end
	
	wins.Parent = leaderstats
	losses.Parent = leaderstats
	level.Parent = leaderstats
	xp.Parent = leaderstats
	totalXP.Parent = leaderstats
	totalPlays.Parent = leaderstats

	leaderstats.Parent = player
	
	game.ReplicatedStorage.Client.Handlers.Gui.StopLoadingScreen:FireClient(player)

	task.delay(1, function()
		game.ReplicatedStorage.Client.Handlers.Gui.MenuAnimation:FireClient(player)
	end)
end

local function save(player, dontLeave, dontWait)
	local userId = player.UserId
	local key = "Player_" .. userId

	local leaderstats = player:FindFirstChild("leaderstats") or player:FindFirstChild("stats")
	
	if player:GetAttribute("SaveDataOnLeave") == false then
		return print(string.format("attempted to save data for %s", player.Name))
	end

	if leaderstats then
		local WaitForStat = function(stat, timeOut)
			if timeOut then leaderstats:WaitForChild(stat, timeOut) else leaderstats:WaitForChild(stat) end
		end 
		
		
		local success

		repeat
			if not dontWait then
				waitForRequestBudget()
			end
			success = pcall(dataStore.UpdateAsync, dataStore, key, function()
				return {
					SessionLock    = dontLeave and os.time() or nil,
					XP             = WaitForStat("XP").Value,
					Wins           = WaitForStat("Wins").Value,
					Level          = WaitForStat("Level").Value,
					Losses         = WaitForStat("Losses").Value,
					TotalXP        = WaitForStat("Total XP").Value,
					TotalPlays     = WaitForStat("Total Matches Played").Value,
				}
			end)
		until success
		
		print(string.format("saved/set data for %s", player.Name))
	end
end

local function onShutdown()
	if RunService:IsStudio() then
		task.wait(2)
	else
		local finished = Instance.new("BindableEvent")
		local allPlayers = Players:GetPlayers()
		local leftPlayers = #allPlayers

		for _,player in ipairs(allPlayers) do
			coroutine.wrap(function()
				save(player, nil, true)
				leftPlayers -= 1
				if leftPlayers == 0 then
					finished:Fire()
				end
			end)()
		end

		finished.Event:Wait()
	end
end

for _,player in ipairs(Players:GetPlayers()) do
	coroutine.wrap(setUp)(player)
end

Players.PlayerAdded:Connect(setUp)
Players.PlayerRemoving:Connect(save)
game:BindToClose(onShutdown)

while true do
	task.wait(60)
	for _,player in ipairs(Players:GetPlayers()) do
		coroutine.wrap(save)(player, true)
	end
end

And also this, if needed
image

Help will be much appreciated.
(If the script looks familiar or something, I used a tutorial)

Why not just do:
XP = leaderstats:WaitForChild(XP).Value?

I don’t know, I preferred making it a function

If you see in the output anything that says: "Attempt to index (x) with (y)"
That means you’re trying to access a dictionary table or property when that value shouldn’t, like trying to do like if a number had properties 123.Value, or the most common one, having a value that should be an instance/class but the value results to be nil. If that’s the case, you should check if the value that’s you’re trying to index really exists, I see you got a pcall function that protects it from any errors, but you didn’t put the function first, which you should for the pcall to really protect from any errors, and then put the arguments (which no idea why you need them, but I’ll let it). If the first argument is a function if I’m not wrong, you can make other pcall functions.

can you try chaning it to just waitforchild or findfirstchild and see if it works? Maybe its something with the function.
If you do that try with absolute path e.g XP = player.leaderstats:findfirstchild("xp).Value

If it still shows nil then check in explorer if the value is in the right place, or if it exist at all

Oh I see it now.

characters limit

I changed them to leaderstats:WaitForChild and no errors or warnings (Infinite yield on x) showed up!

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