Is PlayerRemoving useless?

Yes, you pointed the problem right, but just forget about datastores for now. It’s just additional info, it’s not directly related to the question.

As I described before, I have a line:

activePlayers = PlayerStateService:GetLoadedPlayers()

Which does:

function PlayerStateService.GetLoadedPlayers(self: PlayerStateService): {Player}
	local result = {} :: {Players}

	for _, player in Players:GetChildren() do
		if self:GetAttribute(player, "LoadedModules") then
			table.insert(result, player)
		end
	end

	return result
end

Which was calling:

function PlayerStateService.GetAttribute(self: PlayerStateService, player: Player, attribute: string): any
	return self._playerStates[player][attribute]
end

But because of the fact that I was doing:

	Players.PlayerRemoving:Connect(function(player: Player)
		self._playerStates[player] = nil
	end)

I was in situation when

  • PlayerRemoving is fired, profile is cleared.
  • Players:GetChildren() still returns player.
  • Tries to get attribute, there is no profile, so indexing it with “attribute” fails.