Weird Bug on Tools Script

There’s a rare chance that the player won’t receive the tools, and it all lies within the PreLoadPlayerData() function. The for loops seem to not complete sometimes. And not only that, but I put it in a repeat until loop, and I also added a task.wait() and it seems to not be continuing ??

Script:

-- GLOBAL TABLES
_G.ToolsTableYS = {}

-- SERVICES
local ServerStorage = game:GetService("ServerStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local GroupService = game:GetService("GroupService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

-- VARIABLES
local ToolsFolder = ServerStorage:FindFirstChild("Tools")
local ToolsStore = DataStoreService:GetDataStore("ToolStore")
local LazyModule = require(ReplicatedStorage.Modules.LazyModule)
local DataManager = require(ServerScriptService.Data.DataManager)
local ToolsTable = require(script.ToolsTable)
local PlayerStoredTools = ServerStorage:WaitForChild("PlayerStoredTools", 10)


-- CACHE
local PassCache = {}
local BadgeCache = {}

-- IDS
local UniquePassIDs = {}
local UniqueBadgeIDs = {}
local SeenPasses = {}
local SeenBadges = {}

-- START
for _, data in pairs(ToolsTable) do
	if data["GamepassID"] and not SeenPasses[data["GamepassID"]] then
		SeenPasses[data["GamepassID"]] = true
		table.insert(UniquePassIDs, data["GamepassID"])
	end
	if data["BadgeID"] and not SeenBadges[data["BadgeID"]] then
		SeenBadges[data["BadgeID"]] = true
		table.insert(UniqueBadgeIDs, data["BadgeID"])
	end
end


local function PreLoadPlayerData(player)
	local userId = player.UserId
	local done = 0
	local target = 2
	local signal = Instance.new("BindableEvent")

	local function finish()
		done += 1
		if done >= target then
			signal:Fire()
		end
	end

	task.spawn(function()
		local passes = {}
		for _, passId in ipairs(UniquePassIDs) do
			local ok, owns
			repeat ok, owns = pcall(function() return MarketplaceService:UserOwnsGamePassAsync(userId, passId) end) print("INITTTT") task.wait(0.15)  until ok
			passes[passId] = ok and owns or false
		end
		print("Finished1")
		PassCache[userId] = passes
		finish()
	end)

	task.spawn(function()
		local badges = {}
		for _, badgeId in ipairs(UniqueBadgeIDs) do
			badges[badgeId] = LazyModule:HasBadge(userId, badgeId)
		end
		print("Finished2")
		BadgeCache[userId] = badges
		finish()
	end)

	signal.Event:Wait()
	signal:Destroy()
end


local function GiveTools(player : Player)
	local userId = player.UserId

	local ds = DataManager.Profiles[player].Data.Inventory or {}
	local passes = PassCache[userId] or {}
	local badges = BadgeCache[userId] or {}

	for _, tool in ipairs(ToolsFolder:GetChildren()) do
		local data = ToolsTable[tool.Name]
		if not data then continue end
		if player.Backpack:FindFirstChild(tool.Name) then continue end
		if tool:HasTag("Accessory") then continue end--and table.find(_G.YSTABLE, player.UserId) then continue end

		local shouldGive = false

		if game:GetService("Teams"):FindFirstChild("Contestants") and player.Team == game:GetService("Teams"):FindFirstChild("Contestants") then
			if data["EventBlacklisted"] then
				continue
			end
		end

		if data["Users"] and data["Users"][player.Name] then
			if tool:HasTag("Accessory") then _G.ToolsTableYS[player.UserId][tool.Name] = tool end
			shouldGive = true
		end

		if not shouldGive and data["GamepassID"] and passes[data["GamepassID"]] then
			if tool:HasTag("Accessory") then _G.ToolsTableYS[player.UserId][tool.Name] = tool end
			shouldGive = true
		end

		if not shouldGive and data["DataStore"] and ds[tool.Name] then
			if tool:HasTag("Accessory") then _G.ToolsTableYS[player.UserId][tool.Name] = tool end
			shouldGive = true
		end

		if not shouldGive and data["BadgeID"] and badges[data["BadgeID"]] then
			if tool:HasTag("Accessory") then _G.ToolsTableYS[player.UserId][tool.Name] = tool end
			shouldGive = true
		end

		if data.GroupRole then
			local InGroupInfo = GroupService:GetRolesInGroupAsync(player.UserId, 1074396238)
			if InGroupInfo and InGroupInfo.IsMember then
				for _, role in InGroupInfo.Roles do
					if role.Name == data.GroupRole then
						shouldGive = true
						break
					end
				end
			end
		end

		if shouldGive and not DataManager.ManageStoredTools(player, "Get", tool.Name) then
			DataManager.ManageStoredTools(player, "Add", tool.Name)
		end

		if shouldGive then
			local tools = PlayerStoredTools:FindFirstChild(player.Name)
			if tools and tools:FindFirstChild(tool.Name) then
				continue
			end

			tool:Clone().Parent = player.Backpack
		end
	end
end

ReplicatedStorage.Remotes.GiveToolsAfterPossussion.Event:Connect(function(player)
	if player:IsA("Player") and player and player.Parent  then
		GiveTools(player)
	end
end)


Players.PlayerAdded:Connect(function(player)
	_G.ToolsTableYS[player.UserId] = {}
	repeat task.wait(0.125) until DataManager.Profiles[player]
	task.wait(3)
	PreLoadPlayerData(player)

	if not player:IsDescendantOf(game) then return end

	player.CharacterAdded:Connect(function()
		GiveTools(player)
	end)

	if player.Character then
		GiveTools(player)
	end
end)





Players.PlayerRemoving:Connect(function(player)
	local userId = player.UserId  
	local playerName = player.Name

	_G.ToolsTableYS[userId] = nil
	PassCache[userId] = nil
	BadgeCache[userId] = nil
end)

Assuming it’s getting stuck on this line:

repeat ok, owns = pcall(function() return MarketplaceService:UserOwnsGamePassAsync(userId, passId) end) print("INITTTT") task.wait(0.15)  until ok

Does it get stuck even without the repeat? This repeat will get stuck infinitely if UserOwnsGamePassAsync errors because you’re making ok the until condition

Even without the repeat it still won’t work, I added the repeat in there to make sure it fully works because I originally thought the problem was that it wasn’t going through successfully when I had it without the repeat

i like your idea with the finish.

i suspect things get stuck here

because the signal already has been fired.

considering how complex your code is, i think, you do not need much detailed explanation.
just couple of samples to check so you make own conclusions:

  1. this code
print("1")
task.spawn(function()
	print("2")
end)
print("3")

prints 1 2 3

  1. this code
print("1")
task.defer(function()
	print("2")
end)
print("3")

prints 1 3 2

if you still need explanations feel free to ask.
thank you!