Music script nil error?

So I’m working on a music script with requests and I’m a bit rusty with dev products but somehow the id is coming up as nil even though it plays on the script?

server script:

marketplaceService.ProcessReceipt = function(purchaseInfo)
	local player = players:GetPlayerByUserId(purchaseInfo.PlayerId)
	local songId
	events.paidSong.OnServerEvent:Connect(function(player, id)
		songId = tonumber(id)
	end)
	script.paidPlay.Value = true
	if infoSong.IsPlaying == true then
		infoSong:Stop()
	end
	if songId ~= nil then
		infoSong.SoundId = "rbxassetid://" .. songId
	elseif songId == nil then
		repeat wait() until songId ~= nil
	end
	if not infoSong.IsLoaded then
		infoSong.Loaded:Wait()
	end
	events.changeSong:FireAllClients(songId)
	infoSong:Play()
	if songId ~= nil then
		print("PaidID is nil!")
		paidId = songId
	elseif songId == nil then
		repeat wait() until songId ~= nil
		print("Paid ID is: "..songId)
	end
	return Enum.ProductPurchaseDecision.PurchaseGranted
end

while wait() do
	if script.paidPlay.Value == false then
		local randomSongChosen = math.random(#songs)
		local songChoice = songs[randomSongChosen]
		infoSong.SoundId = "rbxassetid://" .. songChoice
		if not infoSong.IsLoaded then
			infoSong.Loaded:Wait()
		end
		
		events.changeSong:FireAllClients(songChoice)
		infoSong:Play()
		repeat wait() until infoSong.IsPlaying == false
	elseif script.paidPlay.Value == true then
		repeat wait() until infoSong.IsPlaying == false
		if paidId ~= nil then
			if infoSong.SoundId ~= "rbxassetid://" .. paidId then
				script.paidPlay.Value = false
			end
		elseif paidId == nil then
			repeat wait() until paidId ~= nil
			print("Paid ID is: "..paidId)
		end
	end
end

local script:

script.Parent.Frame.RequestButton.MouseButton1Click:Connect(function()
	if script.Parent.Frame.SongID.Text ~= "Song ID" then
		local id = script.Parent.Frame.SongID.Text
		if tonumber(id) then
			local player = players.LocalPlayer
			marketplaceService:PromptProductPurchase(player, skipSongProduct)
			events.paidSong:FireServer(id)
		else
			script.Parent.Frame.SongID.Text = "Please input a number!"
		end
	end
end)

This is the latest output I’m getting
PaidID is nil! - Server - musicHandler:54
14:59:43.542 Paid ID is: 298260734 - Server - musicHandler:83
14:59:57.942 :arrow_forward: PaidID is nil! (x3) - Server - musicHandler:54

I’m stumped, hopefully, someone can spot what’s wrong with my awful logic since I haven’t made a music script in a long time.

Edit: Forgot to add that if I wait around 10 seconds or so and run through the purchase again it has better odds of succeeding, and if it fails once the next purchase without payment will play the id if that’s even a good way to describe it. as well as my music not resuming after purchase which again is most likely caused by my awful logic. And the script sections are the ones that handle the purchasing and song playing.

Maybe because you put the “OnServerEvent” inside a function when you’re basically not supposed to? The structure should be like this:

  1. When the client types in a SongId and presses the request button, fire to the server the SongId.
  2. The server receives it through a remote event (that is not inside any function).
  3. The server stores the SongId in a table with the player’s instance as the key. (Structure: {kom297 = 298260734, another_player = 123456789})
  4. The server triggers MarketPlaceService:PromptProductPurchase.
  5. The server would be able to access the player’s chosen song inside the ProcessReceipt function.

All I’m trying to do is stop the current song and start playing the paid song on everyone which works for the first time but the second purchase never works and it says the song id is nil, even though in the local script it checks and it isn’t nil.

Update: I changed the script around and moved the purchasing out to maybe bring some more success and it kinda worked?
TLDR: first purchase works fine but the second purchase never does but I know the id can’t be nil because the local script that sends the event to the server prints the id but the server says the id is nil on the next purchase.

server script:

while wait() do
	events.purchase.Event:Connect(function(id)
		print("Id sent: "..id)
		
		paidId = id
		infoSong:Stop()
		infoSong.SoundId = "rbxassetid://" .. id
		infoSong:Play()
		events.changeSong:FireAllClients(id)
		
	end)
	if script.paidPlay.Value == false then
		local randomSongChosen = math.random(#songs)
		local songChoice = songs[randomSongChosen]
		infoSong.SoundId = "rbxassetid://" .. songChoice
		if not infoSong.IsLoaded then
			infoSong.Loaded:Wait()
		end
		
		events.changeSong:FireAllClients(songChoice)
		infoSong:Play()
		repeat wait() until infoSong.IsPlaying == false
	elseif script.paidPlay.Value == true then
		repeat wait() until script.paidPlay.Value == false
	end
end

local script:

cript.Parent.Frame.RequestButton.MouseButton1Click:Connect(function()
	if script.Parent.Frame.SongID.Text ~= "Song ID" then
		local id = script.Parent.Frame.SongID.Text
		if tonumber(id) then
			local player = players.LocalPlayer
			print("id is: "..id)
			if id ~= nil then
				marketplaceService:PromptProductPurchase(player, skipSongProduct)
				events.paidSong:FireServer(id)
			elseif id == nil then
				script.Parent.Frame.SongID.Text = "Please try again!"
			end
		else
			script.Parent.Frame.SongID.Text = "Please input a number!"
		end
	end
end)