How to Fix 'attempt to compare number with nil' in Roblox

Last updated:

Quick answer: 'Attempt to compare number with nil' means one side of a <, >, <= or >= comparison is a number and the other is nil. Find which value is nil (a missing attribute, a wrong child name, a value not loaded yet), then give it a default with 'or', or check it with 'if value then' before comparing.

The "attempt to compare number with nil" error happens when you use <, >, <= or >= and one side of the comparison is a number while the other side is nil. Luau can only order two numbers or two strings. If one of them is missing, it stops with this error instead of guessing what you meant.

You will also see the mirrored form, attempt to compare nil with number. The order in the message just tells you which side was nil: the first type named is the left operand, the second is the right operand.

What the Error Looks Like

local price = shopItem:GetAttribute("Price") -- nil if the attribute was never set
local coins = 250

if coins >= price then -- attempt to compare number with nil
    print("Can afford it")
end

GetAttribute returned nil because no attribute named Price exists on that object. The comparison then had a number on one side and nil on the other.

The Most Common Causes

A misspelled or missing attribute. Attribute names are case-sensitive. GetAttribute("price") and GetAttribute("Price") are two different lookups, and a typo returns nil with no warning.

A table key that does not exist. Reading a key that is not in a table gives nil, not an error:

local weapons = {
    Sword = { damage = 10 },
    Bow = { damage = 6 },
}

local damage = weapons.Spear.damage -- this indexes nil, a different error
local level = weapons.Sword.level   -- nil, no error yet
if level > 5 then end               -- attempt to compare nil with number

A value that has not loaded or been set yet. Data from a DataStore, a leaderstat created by another script, or a value waiting on a RemoteEvent can be nil when your code first runs. If you want to understand why timing matters, see fixing attempt to index nil, which covers the same loading problem.

A function that returns nothing on some paths. If a function sometimes forgets to return, the caller receives nil:

local function getLevel(xp)
    if xp > 1000 then
        return 5
    elseif xp > 100 then
        return 2
    end
    -- falls off the end: returns nil for xp <= 100
end

if getLevel(50) > 1 then end -- attempt to compare nil with number

Comparing a string to a number. This one gives a different message (attempt to compare string with number), but people mix the two up. Text read from a TextBox is a string. Convert it with tonumber() first.

How to Find the Nil Value

  1. Click the error line in the Output window. Studio takes you to the exact comparison.
  2. Print both sides right before it, with their types:
print("left:", coins, typeof(coins))
print("right:", price, typeof(price))
if coins >= price then end
  1. Whichever one prints nil nil is the problem. Trace it back to where it was assigned and ask why nothing was stored there.

Printing the type with typeof is useful because a value can look right in the Output but actually be a string like "100".

Fix 1: Provide a Default With or

When a missing value has a sensible fallback, supply it at the point you read it:

local price = shopItem:GetAttribute("Price") or 0
local level = weapons.Sword.level or 1

if level > 5 then
    print("High level weapon")
end

a or b returns b whenever a is nil or false. For numbers this is safe because 0 is truthy in Luau, so a real zero will not be replaced by the default.

Fix 2: Check Before Comparing

When a missing value means the code should not run at all, guard it:

local price = shopItem:GetAttribute("Price")

if price == nil then
    warn("Shop item has no Price attribute:", shopItem:GetFullName())
    return
end

if coins >= price then
    buy(shopItem)
end

The warning matters. A silent return hides the bug and you will spend an hour wondering why the shop does nothing.

Fix 3: Wait for the Value to Exist

If the value is created by another script, wait for the object instead of reading it once:

local leaderstats = player:WaitForChild("leaderstats", 10)
local coins = leaderstats and leaderstats:WaitForChild("Coins", 10)

if coins then
    if coins.Value >= 100 then
        print("Enough coins")
    end
end

Always pass a timeout. Without one, a missing object stalls your script forever and you get the infinite yield warning instead; see the infinite yield fix.

Fix 4: Make Functions Return a Value on Every Path

local function getLevel(xp: number): number
    if xp > 1000 then
        return 5
    elseif xp > 100 then
        return 2
    end
    return 1
end

Adding a return type annotation helps. Studio's type checker will flag a function that does not return a number on every path before you even run the game.

Common Mistakes

Practice It

Nil comparisons show up in almost every economy, level and shop system, so it pays to get fast at spotting them. The Luablox lessons include exercises where you fix broken comparisons, and the problems page has short drills you can run directly in the browser.

Frequently asked questions

What does 'attempt to compare number with nil' mean?

One side of a <, >, <= or >= comparison is a number and the other side is nil. Luau cannot order a number against nothing, so it raises an error. The cause is almost always a value that was never set or has not loaded yet.

What is the difference between 'compare number with nil' and 'compare nil with number'?

They are the same bug seen from different sides. The message lists the left operand type first and the right operand type second, so 'compare nil with number' means the left side was nil, and 'compare number with nil' means the right side was nil.

Does == nil also throw this error?

No. Equality checks work with any types, so value == nil is safe and returns true or false. Only the ordering operators <, >, <= and >= require both sides to be numbers (or both strings).

Is it better to use 'or 0' or an if check?

Use 'or' when a default value is genuinely correct, like a missing level meaning level 1. Use an if check with a warn when a missing value indicates a real bug, such as a shop item without a price, so you notice and fix it instead of hiding it.

Learn core Roblox scripting and Luau programming concepts, including: attempt to compare number with nil, attempt to compare nil with number, attempt to compare number with nil roblox, attempt to compare nil < number, luau compare nil error.

Related pages