Why does my following code yield this error sometimes?

Hello there! I’m having an issue where the following code sometimes yields the following error: Attempt to index nil with 'UserId’ at the block starting where the if arguments == (“award”) is. The code works the majority of the time awarding players with points, however sometimes it just breaks and yields the error. I’m also speculating that it might have to do something with the player leaving and not removing the player properly? Can anyone tell me what I’ve might of done wrong in my code?

local atable = {}`

    script.Parent.A.Touched:Connect(function(touched)
	
	local character = touched.Parent
    local humanoid = character:FindFirstChildWhichIsA("Humanoid")
	local player = game:GetService("Players"):GetPlayerFromCharacter(character)
	
		local AlreadyInTable = false
		if player and humanoid then
		for _,OtherPlayer in next,atable do
			if OtherPlayer == player then
				AlreadyInTable = true
			end
		end
		if not AlreadyInTable then
		table.insert(atable,#atable+1, player)
		end
		end
end)

GlobalEvent.Event:Connect(function(arguments)
	if arguments == ("award") then
		if #atable ~= 0 then
			for i = 1, #atable do
				local plr = atable[i]
				if plr.UserId>0 then
					plr.leaderstats.Wins.Value = plr.Wins.Value + 1
					for Key,OtherPlayer in next,atable do
	        	 		if OtherPlayer == plr then
	              		table.remove(atable,Key)
	              		break
						end
			     	end
				end
			end
		elseif #atable == 0 then
			print("Nothing")
		end
	end
end)

Players.PlayerRemoving:Connect(function(Player)
     for Key,OtherPlayer in next,atable do
          if OtherPlayer == Player then
               table.remove(atable,Key)
               break
          end
     end
end)
2 Likes

This might be incorrect but try replacing your table.insert(atable,#atable+1,player) line with the following:

table.insert(atable,player)

1 Like

This may not be the error as I’ve done this before, the same error still came up even before I keyed where the data should be stored in the table.

1 Like

Have you tried printing what the table object is? That would help the best.

2 Likes

Alrighty! I added more error checking as well as what you suggested and printing out the table and where the data is stored in the table. I also figured that players could be leaving during reward time, so I’ve added an if statement checking if the player is nil. Hopefully during the my next best test I can find a diagnosis. If anyone else still see’s an error in my code please let me know!

2 Likes

Yes, adding a check before trying to get a Player’s UserId is recommended. The player is most likely leaving while given points before the game has time to remove them from the table.

1 Like

If you didn’t see, there are if conditions already in the code checking if a humanoid is nil or not.

	if player and humanoid then
	for _,OtherPlayer in next,atable do
		if OtherPlayer == player then
			AlreadyInTable = true
		end
	end
	if not AlreadyInTable then
	table.insert(atable,#atable+1, player)
	end
	end
1 Like

Use ipairs to iterate over your table instead of in next. ipairs is not only quicker in iterating over tables but it designed for that purpose.

As for your numeric for loop iteration (don’t use it), your code is assuming that a player exists at the index i in the player table. If a player doesn’t exist, then you have a nil value. You need to check for existence.

local plr = atable[i]
-- Why do you need a UserId check...?
if plr and plr.UserId > 0 then
2 Likes

I believe your error is in the following block of code, though it’s difficult to know for certain without the complete error information including the line and column number.

			for i = 1, #atable do
				local plr = atable[i]
				if plr.UserId>0 then
					plr.leaderstats.Wins.Value = plr.Wins.Value + 1
					for Key,OtherPlayer in next,atable do
	        	 		if OtherPlayer == plr then
	              		table.remove(atable,Key)
	              		break
						end
			     	end
				end
			end

You start running a loop from 1, #atable, but then you remove elements from atable when you call table.remove(atable,Key). The outer loop will continue to iterate up to the original value of #atable however not every index will contain a value since you’ve removed values.

You can solve this by verifying the index you’re checking is non-nil, however this still leaves you with a logic error since you’re removing a value and then shifting all values down to fill the gap when you call table.remove.

Since it looks like you’re removing players from the table once you’ve awarded them a win, a better solution would be the following:

while #atable > 0 do
	local plr = table.remove(atable)
	if plr.UserId > 0 then
		plr.leaderstats.Wins.Value = plr.Wins.Value + 1 --should this be .leaderstats.Wins?
	end
end
2 Likes

@colbert2677
Got it! I will switch to this method when I need to iterate through a possible table.

@ComplexGeometry
Agh, how could I’ve missed that error! I did not think of that when I was writing the code. I will definitely fix this right away! Thank you! :slight_smile:

2 Likes