How can I fix this error?

Hi, so my goal in this script is to give an user a tray after clicking this button on my GUI that I’ve made but it is not working and I have ensure that the tool is correctly named as “Tray” and also in the ServerStorage folder.

  11:49:45.195  Infinite yield possible on 'ServerStorage:WaitForChild("Tray")'  -  Studio
  11:49:45.195  Stack Begin  -  Studio
  11:49:45.195  Script 'Players.Berkaygul9.PlayerGui.InteractionGUI.Frame.GetTrayButton.LocalScript', Line 14 - function getTrayModel  -  Studio - LocalScript:14
  11:49:45.195  Script 'Players.Berkaygul9.PlayerGui.InteractionGUI.Frame.GetTrayButton.LocalScript', Line 33 - function giveTrayToPlayer  -  Studio - LocalScript:33
  11:49:45.196  Script 'Players.Berkaygul9.PlayerGui.InteractionGUI.Frame.GetTrayButton.LocalScript', Line 56 - function onGetTrayButtonClicked  -  Studio - LocalScript:56
  11:49:45.196  Stack End

Code:


-- LocalScript inside the GetTrayButton (Verify this again)
local function getTrayModel()
	local serverStorage = game:GetService("ServerStorage")

	--Check Server Storage exists.
	if not serverStorage then
		warn("ServerStorage service not found!")
		return nil
	end

	--Quick wait check (testing).
	wait (1)

	local trayModel = serverStorage:WaitForChild("Tray") -- Set a timeout here.



	return trayModel
end

-- Function to give the player a tray
local function giveTrayToPlayer(player)
	-- Find the player's character and humanoid
	local character = player.Character or player.CharacterAdded:Wait()[1]
	local humanoid = character:FindFirstChild("Humanoid")

	if not humanoid then
		warn("Humanoid not found for player:", player.Name)
		return
	end

	-- Get the Tray MeshPart
	local originalTray = getTrayModel()

	--Check if original tray actually exists.
	if originalTray == nil then
		warn("Tray Model returned as nil.")
		return
	end

	-- Clone the Tray MeshPart
	local tray = originalTray:Clone()

	-- Parent the tray to the player's backpack
	tray.Parent = player.Backpack

	print("Gave tray to player:", player.Name)
end

--Button function (Get Tray)
local function onGetTrayButtonClicked() -- Corrected: No player argument here
	-- Get the local player
	local player = game.Players.LocalPlayer  -- Get Player in event handler!

	--Gives the play the tray.
	giveTrayToPlayer(player)
	--Once they have a tray it will close.
	script.Parent.Parent.Visible = false
end

-- Setup the button
local getTrayButton = script.Parent

-- Check if the button exists before connecting the event
if getTrayButton then
	getTrayButton.MouseButton1Click:Connect(onGetTrayButtonClicked)
else
	warn("GetTrayButton not found in Frame!")
end

6 Likes

Client cannot interact with server-storage.

You should instead use remotes to give tray to the player.

4 Likes

Ah, makes sense. So if I make it into a server script, it wouldn’t give the tray to all the players in the game, right?

1 Like

If you’re going to pass something, then you will need to use a remotefunction, otherwise in this case, we need a remoteEvent.

Create that remoteEvent in replicatedStorage, we will name it as ‘giveTray’ and make the script be connected to it like this:

Based on your script it may look something like this.


local serverStorage = game:GetService("ServerStorage")
local tray = serverStorage:WaitForChild("Tray", 1) -- wait for it to replicate only 1 second.
local replicatedStorage = game:GetService("ReplicatedStorage")
local remote = replicatedStorage:WaitForChild("giveTray", 1) -- wait for rep 1 sec.

remote.OnServerEvent:Connect(function(player)
  -- now we will give the tray to the player.
  local backpack = player.Backpack
  local clone = tray:Clone()
  clone.Parent = backpack
end)

And client would need to get that remote and fire it like this, after pressing that button.

local giveTrayRemote = game:GetService("ReplicatedStorage"):WaitForChild("giveTray", 1) -- wait for rep 1s
giveTrayRemote:FireServer()

Though, this is a very vulnerable example, and you might need to protect it, only if it’s a special item.

2 Likes

I see thanks, this helps out alot!

I’ll also comment about your script.

This line is both unreliable and technically incorrect.

player.CharacterAdded once it gets the character, will return an instance, not a table.
but this is not reliable, you’re not required to have player.CharacterAdded since player.Character already returns a character.

That would now be:

local character = player.Character

Others parts of your code also aren’t implemented well.

So just to make it a bit better, maybe this would be implemented better.


-- LocalScript inside the GetTrayButton.

local replicatedStorage = game:GetService("ReplicatedStorage")
local giveTrayRemote = replicatedStorage:WaitForChild("giveTray", 1)
local plr = game:GetService("Players").LocalPlayer

local function onGetTrayButtonClicked()
	giveTrayRemote:FireServer()
	script.Parent.Parent.Visible = false
end

local getTrayButton = script.Parent
if getTrayButton then
	getTrayButton.MouseButton1Click:Connect(onGetTrayButtonClicked)
end

Hope this works better.

3 Likes