In short
Built-in Luau functions check what you pass them. The message tells you exactly which: argument #1 (the first one) to ipairs should have been a table, but it got nil. So the variable you passed was empty. Find where it should have been set, and check it before the call. The same pattern covers math.floor, string.sub, math.random and the rest.
What the message means
ServerScriptService.Round:30: invalid argument #1 to 'ipairs' (table expected, got nil)
Other forms of the same message:
invalid argument #1 to 'pairs' (table expected, got nil)invalid argument #1 to 'floor' (number expected, got nil)invalid argument #1 to 'sub' (string expected, got nil)invalid argument #2 to 'random' (number expected, got string)
The parts are always the same: the argument position (#1, #2), the function name in quotes, what it expected, and what it got. For a method call such as text:sub(1, 3), the string itself is argument #1.
Roblox engine functions report the same kind of mistake differently, for example Argument 1 missing or nil or Unable to cast value to Object.
Causes and fixes
Three things cause this error in practice. Each one below has the smallest code that triggers it, then the fix.
The table passed to ipairs or pairs is nil
A list that has not been made yet, a key that does not exist in a bigger table, or a function that forgot to return its list.
local rounds = { Lobby = { "Spawn" } }
-- rounds.Arena does not exist:
-- invalid argument #1 to 'ipairs' (table expected, got nil)
for _, name in ipairs(rounds.Arena) do
print(name)
end
Check the table before the loop. In Luau you can also loop over a table directly, without ipairs.
local rounds: { [string]: { string } } = { Lobby = { "Spawn" } }
local arena = rounds.Arena
if arena then
for _, name in arena do
print(name)
end
else
warn("[Round] no Arena list")
end
A maths function got nil
math.floor, math.clamp, math.random and friends need numbers. A missing attribute or table value gives number expected, got nil.
local part = workspace:WaitForChild("Platform")
-- no "Speed" attribute on the part:
-- invalid argument #1 to 'floor' (number expected, got nil)
local speed = math.floor(part:GetAttribute("Speed"))
print(speed)
Read the value, check that it is a number, and use a default when it is not.
local part = workspace:WaitForChild("Platform")
local raw = part:GetAttribute("Speed")
local speed = if typeof(raw) == "number" then math.floor(raw) else 16
print(speed)
The argument is the wrong type
Text from a TextBox is a string; math.random(1, box.Text) fails with number expected, got string when the text is not a number. Passing an object where a string is wanted fails the same way.
local box = script.Parent
box.FocusLost:Connect(function()
-- invalid argument #2 to 'random' (number expected, got string)
print(math.random(1, box.Text))
end)
Convert with tonumber (or tostring) and check the result before the call.
local box = script.Parent :: TextBox
box.FocusLost:Connect(function()
local sides = tonumber(box.Text)
if sides and sides >= 1 then
print(math.random(1, math.floor(sides)))
end
end)
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
What does argument #1 mean?
The first value inside the brackets. #2 is the second, and so on. With a colon call such as name:sub(1, 3), the value before the colon counts as #1.
Why table expected, got nil?
The variable you passed to ipairs or pairs was empty. Print it just above the loop to confirm, then find out why it was never set.
Is this the same as attempt to iterate over a nil value?
It is the same mistake. Looping over nil directly says attempt to iterate over a nil value; passing nil to ipairs or pairs gives this message.
Can RoCode fix it?
Yes. Paste the Output line into RoCode. It finds the call in the script in your open place, traces where the argument should come from and adds the missing check or conversion.
Sources and further reading
- Roblox Creator Docs: math library
- Roblox Creator Docs: string library
- Roblox Creator Docs: ipairs and pairs
How the code was checked: every block marked Fixed passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 23 October 2026), and every block marked Breaks compiles and fails only when it runs. The message wording was checked by running the broken code with the Luau command line tool on 23 October 2026. A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.