In short
+, -, *, / and the other maths operators only work on numbers (and on Roblox types such as Vector3 with the right partner). The word in brackets is the operation (add, sub, mul, div), and the two types after it are what Luau actually got. nil and number means the left side was missing, Instance and number means you forgot .Value, string and number means text that needs tonumber.
What the message means
ServerScriptService.Rewards:11: attempt to perform arithmetic (add) on nil and number
Other forms of the same message:
attempt to perform arithmetic (add) on Instance and numberattempt to perform arithmetic (sub) on string and numberattempt to perform arithmetic (mul) on table and number
Read the two types in the message in order: they are the left and right side of the operator. In coins + 1, (add) on nil and number means coins was nil and 1 was the number.
Luau never treats a missing value as 0, and it only turns text into a number when the text looks like one. Do both on purpose: (value or 0) for a missing number, tonumber(text) for text.
Causes and fixes
Three things cause this error in practice. Each one below has the smallest code that triggers it, then the fix.
- A table value was never set (nil)
- An IntValue was used without .Value
- The value is text, from a TextBox or an attribute
A table value was never set (nil)
Reading a key that is not in a table gives nil. Adding to it, as in kills[player] += 1 the first time a player scores, fails because there is nothing to add to yet.
local kills = {}
local function addKill(player)
-- first kill: kills[player] is nil
-- attempt to perform arithmetic (add) on nil and number
kills[player] += 1
end
addKill("Builderman")
Start the value at 0 with (kills[player] or 0), or set it when the player joins.
local kills: { [string]: number } = {}
local function addKill(playerName: string)
kills[playerName] = (kills[playerName] or 0) + 1
end
addKill("Builderman")
An IntValue was used without .Value
leaderstats.Coins is an IntValue object, not a number. Doing maths on the object gives (add) on Instance and number.
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
local coins = player:WaitForChild("leaderstats"):WaitForChild("Coins")
-- attempt to perform arithmetic (add) on Instance and number
coins = coins + 10
end)
Read and write .Value on the object.
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player: Player)
local leaderstats = player:WaitForChild("leaderstats", 10)
local coins = leaderstats and leaderstats:WaitForChild("Coins", 10)
if coins and coins:IsA("IntValue") then
coins.Value += 10
end
end)
The value is text, from a TextBox or an attribute
A TextBox's Text is always a string, even when the player typed digits. A string with non-digit text in maths fails with (mul) on string and number. Luau quietly converts text that looks like a number, such as "5", which is why the bug only shows up when a player types something else. Convert it on purpose instead.
local box = script.Parent
box.FocusLost:Connect(function()
-- "abc" or "" in the box: attempt to perform arithmetic (mul) on string and number
local doubled = box.Text * 2
print(doubled)
end)
tonumber turns text into a number, or nil when it is not one. Check the result before you use it.
local box = script.Parent :: TextBox
box.FocusLost:Connect(function()
local amount = tonumber(box.Text)
if amount == nil then
box.Text = "Type a number"
return
end
print(amount * 2)
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 (add) mean in the message?
It is the operation that failed: add for +, sub for -, mul for *, div for /, and so on. The two types after it are the left and right side.
Why does it say Instance and number?
You did maths on a Roblox object, usually an IntValue or NumberValue, instead of its number. Use .Value: coins.Value += 10.
How do I treat a missing value as 0?
Write (value or 0). If value is nil, the expression gives 0. Do this where the number is read, not by hiding the error with pcall.
Can RoCode fix it?
Yes. Paste the Output line into RoCode. It finds which side of the maths is wrong in the script in your open place and adds the default, the .Value or the tonumber check.
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 and against the message strings in Roblox Studio itself on 23 October 2026. A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.