In short
:Connect() needs a function to run later, and it got something else, nearly always nil. Three mistakes cause it: writing Connect(onTouched()), which runs the function now and passes what it returns; connecting a function that is defined further down the script, so it does not exist yet on that line; or a misspelt name, such as a function in a ModuleScript that is called something slightly different. Pass the function itself, with no brackets, and define it above the line that connects it.
What the message means
Workspace.Lava.Script:9: Attempt to connect failed: Passed value is not a function
Every event in Roblox (Touched, PlayerAdded, Activated, a RemoteEvent's OnServerEvent) has a Connect method that stores the function you give it and calls it each time the event fires. If the value is not a function, there is nothing to call, so Roblox refuses straight away.
Causes and fixes
Three things cause this error in practice. Each one below has the smallest code that triggers it, then the fix.
- The function is called instead of passed
- The function is defined below the Connect line
- The name in a ModuleScript is misspelt
The function is called instead of passed
The brackets after the name run the function immediately. Connect then receives whatever it returned, which is nil for a function with no return.
local lava = script.Parent :: BasePart
local function onTouched(hit: BasePart)
local humanoid = hit.Parent and hit.Parent:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.Health = 0
end
end
-- onTouched() runs now and returns nil: Attempt to connect failed: Passed value is not a function
lava.Touched:Connect(onTouched())
Pass the name without brackets. If you need to give the function extra values, wrap the call in a new function: Connect(function(hit) onTouched(hit, 50) end).
local lava = script.Parent :: BasePart
local function onTouched(hit: BasePart)
local humanoid = hit.Parent and hit.Parent:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.Health = 0
end
end
lava.Touched:Connect(onTouched)
The function is defined below the Connect line
A script runs from top to bottom. A local function written after the Connect line does not exist yet when that line runs, so the name is an empty global and its value is nil.
local Players = game:GetService("Players")
-- onPlayerAdded does not exist yet: Attempt to connect failed: Passed value is not a function
Players.PlayerAdded:Connect(onPlayerAdded)
local function onPlayerAdded(player: Player)
print("Welcome", player.Name)
end
Move the function above the line that connects it. The Script Editor underlines the name in the broken version with an Unknown global warning, which is the quickest way to spot this.
local Players = game:GetService("Players")
local function onPlayerAdded(player: Player)
print("Welcome", player.Name)
end
Players.PlayerAdded:Connect(onPlayerAdded)
The name in a ModuleScript is misspelt
Connecting Shop.onBuy when the module defines Shop.OnBuy passes nil, because Luau names are case-sensitive and a missing key in a table is nil.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Shop = {}
function Shop.OnBuy(player: Player, itemName: string)
print(player.Name, "wants", itemName)
end
local buyRemote = ReplicatedStorage:WaitForChild("BuyItem") :: RemoteEvent
-- Shop.onBuy is nil (the function is Shop.OnBuy): Attempt to connect failed
buyRemote.OnServerEvent:Connect((Shop :: any).onBuy)
Use the exact name. With --!strict at the top of the script, the Script Editor flags a key that the table does not have before you press Play.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Shop = {}
function Shop.OnBuy(player: Player, itemName: unknown)
if typeof(itemName) ~= "string" then
return
end
print(player.Name, "wants", itemName)
end
local buyRemote = ReplicatedStorage:WaitForChild("BuyItem") :: RemoteEvent
buyRemote.OnServerEvent:Connect(Shop.OnBuy)
Fix it in your place
Paste the error, RoCode fixes it in your place
Copy the line from Output and paste it here. RoCode opens the script it names in the place you have open in Studio, works out which of the causes above it is, and edits the code there instead of handing you a snippet to paste.
RoCode is an AI agent for Roblox Studio: it reads the scripts in the place you have open, finds the line and edits it there, and every change is an undo point. It runs on Windows or macOS with a desktop browser. Free to start, with free credits every day.
How to find the line that causes it
- Open Output (Window menu, or the Script tab), clear it with Ctrl+K (⌘K on Mac), and press Play.
- Find the first red line. It starts with the script's place in the Explorer and the line number, such as
ServerScriptService.Shop:12:. - Click the red line. Studio opens that script with the cursor on the failing line.
- Read the lines between
Stack BeginandStack Endunder it: they list the calls that led there, newest first, so you can see which function called the broken one. - Still not sure which value is wrong? Add
print(typeof(x), x)just above the line, or set a breakpoint on it and read the values in the Watch window.
Questions
How do I pass arguments to a function I connect?
Wrap it: part.Touched:Connect(function(hit) damage(hit, 25) end). The outer function is what Connect stores; it calls yours with the extra value each time the event fires.
Can I send a function through a RemoteEvent and connect it?
No. Roblox does not send functions across the client and server boundary; the receiving side gets nil, and connecting that gives this error. Send a name or an ID instead and look the function up on the receiving side.
Why does the error point at a different script?
The line in Output is the line that called Connect. If a ModuleScript connects a function that another script passed in, the mistake is in the script that passed it. Read the stack lines under the error to see the full path.
Can RoCode fix it?
Yes. Paste the Output line into RoCode. It reads the script in the place you have open, finds what was passed to Connect and fixes the call, the order or the name.
Sources and further reading
- Roblox Creator Docs: RBXScriptSignal. Connect, Once and ConnectParallel take a function
- Roblox Creator Docs: events
- Roblox Creator Docs: functions
How the code was checked: every block marked Fixed passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 4 November 2026), and every block marked Breaks compiles and fails only when it runs. The message wording was checked against the message strings in Roblox Studio itself (macOS build installed on 24 October 2026) on 4 November 2026. A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.