bad argument #1 to 'X' (number expected, got nil): FiveM Lua fix
Getting 'bad argument #1 to X (number expected, got nil)' in FiveM? How to read the argument number and fix nil entities, pairs(nil), tonumber and table errors.
Somewhere in your console, a script stops with this:
SCRIPT ERROR: @my_script/client/main.lua:57: bad argument #1 to 'floor' (number expected, got nil)A function was called with an argument it cannot use, and the argument is almost always nil. The message tells you which function, which argument and what type it wanted. This guide shows how to read it and the usual sources of the nil.
How to read the message
bad argument #1 to 'X' (number expected, got nil)Xis the name of the function that complained.#1is the position of the argument:#1is the first one,#2the second.number expectedis the type the function needs. It can also saystring,tableorboolean.got nilis what it actually received. It can also begot table,got stringorgot no value.
Open the line from the error and look at the function named in the message. Then look at the argument in that position and ask where it comes from.
local price = Config.Prices[item]
local rounded = math.floor(price) -- bad argument #1 to 'floor' (number expected, got nil)Here Config.Prices[item] is nil, because item is not a key of the table. The error is on the math.floor line, but the mistake is in the data.
table expected, got nil
The same message with a table appears with table functions:
bad argument #1 to 'insert' (table expected, got nil)local list
table.insert(list, 'a') -- list was never createdCreate the table before you use it:
local list = {}
table.insert(list, 'a')For a table that lives in a shared structure, create it when it is missing:
players[source] = players[source] or {}
table.insert(players[source], item)Looping over nil: pairs and ipairs
In Lua 5.3 and 5.4, which FiveM uses, looping over nil fails with a message that names the loop instead of pairs:
bad argument #1 to 'for iterator' (table expected, got nil)for _, job in pairs(Config.Jobs) do -- Config.Jobs is nilCheck where the table is defined: a typo in the name, the config file not loaded by the manifest, or data that did not arrive yet. A short guard avoids the crash while you find the real cause:
for _, job in pairs(Config.Jobs or {}) doUse it as a safety net, not as a fix. If Config.Jobs should exist, an empty loop only hides the bug. The related message table index is nil covers missing keys in nested config tables.
Natives that receive nil
Many natives need a number, such as an entity handle. A handle that is nil or 0 usually means the entity does not exist (yet).
local vehicle = GetVehiclePedIsIn(ped, false)
local plate = GetVehicleNumberPlateText(vehicle) -- vehicle is 0 when the ped is on footCommon sources:
- The entity is not loaded. A vehicle spawned by the server is not available to your client for a moment. On the client, wait until it exists:
local vehicle = NetToVeh(netId)
local timeout = 0
while not DoesEntityExist(vehicle) and timeout < 100 do
Wait(50)
vehicle = NetToVeh(netId)
timeout = timeout + 1
end- A function returned nothing.
GetPlayerPed(-1),GetClosestVehicleand similar can return0when nothing matches. Check the value before you use it. - A wrong vector. A native that wants three numbers,
x, y, z, does not accept a whole table. Passcoords.x, coords.y, coords.z, or use avector3where the native takes one. - A missing key in the config.
Config.Spawn.xis nil whenConfig.Spawnis written with[1],[2],[3].
The exact text depends on the native, and some natives do not raise an error at all but do nothing. That is why a guard is worth adding:
if vehicle ~= 0 and DoesEntityExist(vehicle) then
SetVehicleEngineOn(vehicle, true, true, false)
endtostring, tonumber and string.format
Conversion functions are another source of nil:
tonumber('abc')returnsnil, not an error, so the crash comes later when you use the result.tostring(value)always returns a string, even fornil(it gives'nil'), so it is safe to use when you build a text.string.format('%d', value)fails whenvalueisnil:bad argument #2 to 'format' (number expected, got nil).
When a number comes from a player or from a command, check it:
RegisterCommand('pay', function(source, args)
local amount = tonumber(args[1])
if not amount then
return print('Usage: /pay [amount]')
end
print(('Paying %d'):format(amount))
end)Note args[1] is nil when the player typed /pay alone, and tonumber(nil) returns nil, so the check above covers both cases.
Find the nil
When the source is not obvious, print the values just before the failing line:
print('item', item, type(item))
print('price', Config.Prices[item], type(Config.Prices[item]))Then trace the nil back to where it should have been set. Remove the prints when you are done.
Checklist
| Symptom | Fix |
|---|---|
bad argument #1 to 'floor' (number expected, got nil) |
The value is missing: check the key or variable that feeds it |
bad argument #1 to 'insert' (table expected, got nil) |
Create the table first: t = t or {} |
bad argument #1 to 'for iterator' (table expected, got nil) |
The table you loop over is nil; check its name and where it is filled |
| A native fails on an entity | Check DoesEntityExist(entity) and wait for the entity to load |
tonumber(...) gives nil |
Validate player input before you use it |
bad argument #2 to 'format' |
%d and %s need a real value; check the argument in that position |
If the error is about something being nil instead of a bad argument, read attempt to compare nil and attempt to call a nil value.
Quick answers
What does 'bad argument #1 to X (number expected, got nil)' mean?
A function received nil as its first argument where it needs a number. X is the function, #1 is the position of the argument, and nil is what your code passed.
How do I fix 'bad argument #1 to for iterator (table expected, got nil)'?
You looped over a variable that is nil with pairs or ipairs. Find where that variable is filled and check it exists, or loop over variable or {}.
Can a native receive nil without an error?
Depending on the native, a nil or invalid value may be treated as 0 or simply do nothing, so the bug can hide. Check an entity with DoesEntityExist(entity) before you use it.
Scripts that skip this problem
Advanced BoostingTablet-driven vehicle boosting: contracts from class D to S+, crews and a live queue.View script →
CCTV Security CamerasPlaceable cameras, a live multi-view tablet and printed evidence photos.View script →
Item Creator V2Create usable items with animations, props, effects and more — without writing code.View script →