Attempt to index nil with 'UserId' How to fix it?

local Players = game:GetService(“Players”)
local DataStoreService = game:GetService(“DataStoreService”)
local RunService = game:GetService(“RunService”)

local dataStore = DataStoreService:GetDataStore(“Test”) – Always set Datastore to Official when game is ready.

– Function to create leaderstats for a player
local function createLeaderstats(player)
local userID = player.UserId
local key = “Player_”…userID

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

-- Example of a score stat
local clicks = Instance.new("IntValue")
clicks.Name = "Clicks"
clicks.Value = 0
clicks.Parent = leaderstats --NL

local success, returnValue
success, returnValue = pcall(dataStore.GetAsync, dataStore, key)


if success then
	if returnValue == nil then
		returnValue = {
			Clicks = 0, -- NL

		}
	end

	print(returnValue)
	clicks.Value = if returnValue.Clicks ~= nil then returnValue.Clicks else 0 --NL
else
	player:kick("There was an error loading your data :(. Roblox's Datastore might be down, if not contact out group!")
	print(player.Name.."Data loading ERROR!")
end

end

local function save(player)
local userID = player.UserId
local key = “Player_”…userID

local clicks = player.leaderstats.Clicks.Value --NL

local dataTable = {
	Clicks = clicks, --NL
}
print(dataTable)

local success, returnValue
success, returnValue = pcall(dataStore.UpdateAsync, dataStore, key, function()
	return dataTable
end)

if success then
	print("Data Saved!")
else
	print("Data Saving ERROR:(")
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)
			leftPlayers -= 1
			if leftPlayers == 0 then
				finished:Fire()
			end
		end)()
	end
	finished.Event:Wait()
end

end

– Connect the createLeaderstats function to the PlayerAdded event
Players.PlayerAdded:Connect(createLeaderstats)

– Iterate through all existing players and create leaderstats for them
for _, player in Players:GetPlayers() do
createLeaderstats(player)
end
Players.PlayerRemoving:Connect(save()

)

game:BindToClose(onShutDown)

I think I have to fix this section, but i don’t know how:

local function save(player)
local userID = player.UserId
local key = “Player_”…userID

You have an extra dot on concatenating the strings.
Should be .., not ....
local key = "Player_".. userID

I did that but still not working

error message is : 21:48:15.419 ServerScriptService.leaderstats:46: attempt to index nil with ‘UserId’ - Server - leaderstats:46

The error is for this line:
local userID = player.UserId

Could you print the player?

print(player)

And point out the line that errors

Hi,

Could you please show me how you’re getting the player so I can further assist you?

“attempt to index nil with ‘IDENTIFIER’”
usually occurs when an expression like so: “apple.Material” fails to evaluate due to ‘apple’ evaluating to nil like so: “nil.Material”.

in this case, a variable named player is nil.
first of all:

--iterate through all existing players and create leaderstats for them
for _, player in Players:GetPlayers() do
createLeaderstats(player)
end

is not needed, because server scripts run before client scripts, so if you subscribe createLeaderstats to PlayerAdded it will be enough, when the for loop runs there will not be any existing players.

anyway, to fix this issue, try modifying this line:

--the bug, in roblox lua, you pass the name of the function, not a callexpression.
Players.PlayerRemoving:Connect(save())

you are invoking the function by saying save(), so instead of subscribing the function, it will call the function, and subscribe the result. but since save is called without any arguments, player is evaluated to nil, causing the error.

consider changin the line mentioned above to:

--pass the methodgroup/name of the function, without calling it.
Players.PlayerRemoving:Connect(save)

hope this helps!

I have an idea for your problem, hope this will help you:

local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local DSS = game:GetService("DataStoreService")
local runService = game:GetService("RunService")
local database = DSS:GetDataStore("Test1")

local data = {}

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

	local clicks = Instance.new("IntValue")
	clicks.Name = "Clicks"
	clicks.Parent = ldr

	if data[player.UserId] and data[player.UserId].Clicks then
		clicks.Value = data[player.UserId].Clicks
	else
		clicks.Value = 0
	end
end

local function LoadData(player)
	local success, playerData
	local attempt = 1

	while not success and attempt < 4 do
		success, playerData = pcall(function()
			return database:GetAsync(player.UserId)
		end)
		if not success then
			attempt += 1
			warn(playerData)
			task.wait()
		end
	end

	if success then
		print("Data Loaded Successfully")
		if not playerData then
			print("New player, giving default data")
			playerData = {Clicks = 0}  -- Default data for new players
		end

		data[player.UserId] = playerData
		print(data[player.UserId])

		createLeaderstats(player)

		local numberOfClicks = player.leaderstats.Clicks

		numberOfClicks.Changed:Connect(function()
			data[player.UserId].Clicks = player.leaderstats.Clicks.Value
		end)
	else
		warn("Unable to get data for player", player.UserId)
		player:Kick("There was a problem loading your data! Message the developer on Roblox if this problem continues!")
	end
end

Players.PlayerAdded:Connect(LoadData)

local function saveData(player)
	if data[player.UserId] then
		print(data[player.UserId])
		local success
		local playerData
		local attempt = 1

		while not success and attempt < 4 do
			success, playerData = pcall(function()
				database:SetAsync(player.UserId, data[player.UserId])
			end)

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

		if success then
			print("Data saved successfully")
		else
			warn("Unable to save data for", player.UserId)
		end
	else
		warn("No Data for", player.UserId)
	end
end

Players.PlayerRemoving:Connect(function(player)
	saveData(player)
	data[player.UserId] = nil -- Reset player Data
end)

game:BindToClose(function()
	if not runService:IsStudio() then
		for _, player in pairs(Players:GetPlayers()) do
			task.spawn(function()
				saveData(player)
			end)
		end
	else
		print("Roblox Studio")
	end
end)

I have tried both of your guys Ideas, but none has worked to save and load data.

I have used this video to help me code the datastore:

I think the data saves but dosen’t load

Thanks for the help I no longer have the error message. But I think I need to add a load data code. Any help on this?

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