How to Fix 'attempt to perform arithmetic on nil' in Roblox
Quick answer: The error means one operand of a math expression was nil: a missing attribute, a failed tonumber, or a remote argument the client never sent. Initialize the value with a typeof check or an 'or 0' default before doing math on it.
Luau only does math on numbers. If either side of +, -, *, /, //, %, or ^ is nil, the VM stops and prints attempt to perform arithmetic on a nil value. Studio often names the operator too, such as (add) or (mul).
nil is not 0. It means there is no value. A missing attribute, a failed tonumber, an unassigned local, or a remote argument the client never sent all show up as nil. Adding to any of those is this error.
Luablox.dev is a browser-based Roblox and Luau course, not an exploit or executor. luablox.com is a different site.
What the error looks like in Studio
Here is a join-bonus script that crashes the first time a player arrives:
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
local coins = player:GetAttribute("Coins")
player:SetAttribute("Coins", coins + 50) -- coins is nil
end)
GetAttribute returns nil when the attribute does not exist yet. coins + 50 is then arithmetic on nil.
The same crash shows up when:
- You write
kills = kills + 1beforekillshas a number (and you skippedlocal). tonumber(textBox.Text)fails on"abc"and you add the result.- An
OnServerEventhandler doesamount + bonusand the client omittedamount. - You read
data.Levelfrom a table that has noLevelkey, then add XP to it.
If the Output says attempt to index nil with instead, you are past the number and into a missing Instance. Fix the Instance first. This page is only about math on nil.
Fix the value before you compute
Decide what "missing" should mean, then make that explicit. Starting coins are 0, not nil.
local Players = game:GetService("Players")
local STARTING_COINS = 0
local JOIN_BONUS = 50
Players.PlayerAdded:Connect(function(player)
local coins = player:GetAttribute("Coins")
if typeof(coins) ~= "number" then
coins = STARTING_COINS
end
player:SetAttribute("Coins", coins + JOIN_BONUS)
end)
typeof is the Roblox-aware check. type(coins) == "number" also works for primitives. coins or 0 is a shorter default. For numbers it is usually fine, because 0 is truthy in Luau. Prefer the typeof branch when the value might be the wrong type, not only missing.
If the number lives on an Instance, do not assume the Instance exists:
local leaderstats = player:FindFirstChild("leaderstats")
local coinsValue = leaderstats and leaderstats:FindFirstChild("Coins")
if not coinsValue then
return
end
coinsValue.Value += 1
FindFirstChild returns nil when the child is missing. Guard that nil, then do math on .Value. Indexing a missing child is a different error. Get the object, then compute.
How to find the nil
Print both sides of the operator:
print("coins", coins, typeof(coins))
The Output window tells you which argument is nil. Work backwards: which line was supposed to set it, and did that line run? On a remote handler, print every argument before you use it. If amount is nil, the client never sent a number (or you connected the wrong remote).
A NumberValue that exists still has a .Value of 0 by default, not nil. If .Value math is failing, you do not have the NumberValue. You have nil.
Once the types make sense, this error goes away. The free theory lesson on variables and data types covers nil, number, and typeof. First lessons are free. Premium unlocks the full curriculum. You can try a matching practice problem in the live editor, where plain-English errors point at the same mistake Studio is showing you.
Common places the nil hides
The error names the operator, not the variable, so the nil often comes from farther up than the failing line:
- A global that only gets its number inside one branch:
kills = kills + 1runs, but the branch that setkills = 0never did. - An optional remote argument: an
OnServerEventhandler receivesnilfor arguments the client omitted, andamount + bonusthen fails. - A
tonumberon player text:tonumber("abc")returnsnil, and the next line does math on the result. - A table read on the wrong key:
data.Coinsisnilwhen the save file usescoins, or the player has no save yet.
Next: Variables & Data Types
Frequently asked questions
What does 'attempt to perform arithmetic on a nil value' mean in Roblox?
One side of a math expression (+, -, *, /, //, %, or ^) was nil at runtime. A missing attribute, a failed tonumber, an unassigned local, or a remote argument the client never sent are the usual sources.
Why is my Coins attribute nil on the first join?
GetAttribute returns nil until something sets the attribute. Initialize the value with a typeof check or a 'coins or 0' default before doing math on it, so the first join behaves like every other session.
Is nil the same as 0 in Luau?
No. nil means no value exists, while 0 is a number you can do math on. Luau only errors when an operand is truly nil, which is why initializing to 0 fixes the crash.
How do I find which operand is nil?
Print both operands with typeof just before the failing line, for example print("coins", coins, typeof(coins)). The Output window shows which one is nil, then trace back to the line that should have set it.
Understand loop structures in Luau, including numeric, while, generic pairs, and ipairs iterators.