Roblox Studio error

invalid argument #1 to 'ipairs' (table expected, got nil)

What invalid argument #1 to 'ipairs' (table expected, got nil) means in Roblox Studio, the three things that cause it with the code that triggers each, and the fix for each one.

Updated 23 October 20263 min readErrorLuau

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.

On this page
  1. What it means
  2. Causes and fixes
  3. Fix it with RoCode
  4. Find the line
  5. Questions
  6. Sources

What the message means

Output (example)
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.

Breaks Script in ServerScriptService named Round
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.

Fixed Script in ServerScriptService named Round
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.

Breaks Script in ServerScriptService named Platform
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.

Fixed Script in ServerScriptService named Platform
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.

Breaks LocalScript in a TextBox in StarterGui named Dice
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.

Fixed LocalScript in a TextBox in StarterGui named Dice
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.

For example: ServerScriptService.Round:30: invalid argument #1 to 'ipairs' (table expected, got nil)

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

  1. Open Output (Window menu, or the Script tab), clear it with Ctrl+K (⌘K on Mac), and press Play.
  2. Find the first red line. It starts with the script's place in the Explorer and the line number, such as ServerScriptService.Shop:12:.
  3. Click the red line. Studio opens that script with the cursor on the failing line.
  4. Read the lines between Stack Begin and Stack End under it: they list the calls that led there, newest first, so you can see which function called the broken one.
  5. 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

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.

Stop hunting errors line by line.

RoCode reads the scripts in your open place, fixes the error where it happens and tells you what it changed. Free every day, no card required.