attempt to compare number with nil / attempt to perform arithmetic on a nil value: corregir
Corregir 'attempt to compare number with nil' y 'attempt to perform arithmetic on a nil value' en FiveM: datos de jugador sin cargar, valores de config faltantes, tonumber y valores seguros predeterminados con `or`.
Salida de consola:
SCRIPT ERROR: @my_script/server/main.lua:58: attempt to compare number with nil
SCRIPT ERROR: @my_script/client/main.lua:91: attempt to perform arithmetic on a nil value (field 'money')Una línea del script usa un valor que aún no existe en una comparación o un cálculo. Aquí está lo que generalmente deja el valor vacío, y cómo hacer el script seguro.
Qué significa el error
Lua te da nil para cualquier variable o entrada de tabla que no tenga valor. Comparar (<, >, <=) o calcular (+, -, *, /) con nil detiene el script con uno de estos mensajes:
attempt to compare number with nil(oattempt to compare nil with number): un lado de la comparación esnil.attempt to perform arithmetic on a nil value: un cálculo usa una variablenil. Cuando Lua conoce el nombre, lo agrega, como(field 'money')o(local 'price').
El número de línea en el mensaje es la línea con la comparación o la suma. El nil es uno de los valores en esa línea. Imprímelos para ver cuál es:
print('price', price, type(price))
print('count', count, type(count))
if price > count then
-- ...
end1. Los datos del jugador aún no se cargan
La causa más común: el script lee el jugador antes de que el framework haya terminado de cargarlo, por ejemplo en las primeras líneas de un archivo, o en un hilo que comienza a la vez.
-- runs too early on the client: money is nil
local money = ESX.GetPlayerData().money
if money > 100 then
-- ...
endEspera el evento cargado del framework, y lee los datos desde allí:
-- ESX client
local PlayerData = {}
RegisterNetEvent('esx:playerLoaded', function(xPlayer)
PlayerData = xPlayer
end)-- QBCore client
local QBCore = exports['qb-core']:GetCoreObject()
local PlayerData = {}
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
end)En el servidor, un objeto de jugador también puede ser nil cuando la id es incorrecta o el jugador ha salido. Verifica antes de usarlo:
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return endlocal Player = QBCore.Functions.GetPlayer(source)
if not Player then return endEn QBox, el equivalente es exports.qbx_core:GetPlayer(source), con la misma verificación nil.
Consejo: si el script se reinicia mientras estés en el servidor,
playerLoadedya se ha disparado y no se disparará nuevamente. Lee los datos una vez cuando el recurso comienza también.
2. Falta un valor de config
Agregaste una línea a config.lua que el script no tiene, o el script lee una clave que tu config anterior no contiene. Después de una actualización, un config.lua antiguo es una causa muy común.
-- config.lua of the old version has no Config.Price
if playerMoney >= Config.Price then
-- ...
endCompara tu config con la que se envía con la nueva versión, y agrega las claves faltantes. En tu propio código, da a cada configuración un valor predeterminado:
local price = Config.Price or 1003. El valor es una cadena, no un número
Los valores de una base de datos, un cuadro de entrada en un menú o un mensaje JSON a menudo llegan como texto. Comparar una cadena con un número da un error diferente (attempt to compare number with string), pero una conversión que falla te da nil, que trae este error nuevamente. tonumber convierte, y retorna nil cuando no puede:
local amount = tonumber(data.amount)
if not amount then
return -- not a number: stop here
end4. Usa or para un valor predeterminado
or retorna el lado derecho cuando el lado izquierdo es nil (o false). Es la forma más corta de hacer un cálculo seguro:
local count = tonumber(data.count) or 0
local total = (item.price or 0) * countÚsalo donde un valor faltante realmente puede significar cero, como un bonificador opcional. Donde un valor faltante es un error, por ejemplo un precio que debe existir, detente con un mensaje claro en lugar de ocultarlo:
local price = Config.Items[name] and Config.Items[name].price
if not price then
print(('no price set for %s'):format(name))
return
end5. Un resultado de base de datos o devolución de llamada está vacío
Una consulta que no encuentra ninguna fila da nil o una tabla vacía. Leer una columna de ella falla:
local row = MySQL.single.await('SELECT balance FROM bank WHERE owner = ?', { identifier })
if row.balance > 0 then -- row is nil when the player has no row
-- ...
endVerifica la fila primero:
local row = MySQL.single.await('SELECT balance FROM bank WHERE owner = ?', { identifier })
local balance = row and row.balance or 0Lo mismo aplica para las devoluciones de llamada del servidor: la respuesta puede ser nil si la devolución de llamada no fue encontrada o no retornó nada. Si tu script espera en una devolución de llamada, maneja ese caso. Relacionado: attempt to call a nil value es el error hermano cuando una función, no un valor, falta.
6. Un error tipográfico en un nombre de campo
xPlayer.money y xPlayer.Money son diferentes. Al igual que price y Price. El mensaje de error a menudo nombra el campo: verifica su ortografía contra la documentación del framework o contra la tabla que imprimes con print(json.encode(data)).
Lista de verificación
| Síntoma | Solución |
|---|---|
| Error justo después de unirse | Espera el evento del jugador cargado antes de leer datos del jugador |
xPlayer o Player es nil en el servidor |
Verifica if not xPlayer then return end y el id de source |
| Error después de actualizar un script | Agrega las nuevas claves del config.lua enviado al tuyo |
| El valor viene de un menú o JSON | Convierte con tonumber(value) y verifica que no sea nil |
| Un valor puede estar faltando a propósito | Usa value or 0 como valor predeterminado |
| La consulta de base de datos retorna nada | Verifica que la fila no sea nil antes de leer sus columnas |
| El campo es nil aunque debería existir | Verifica la ortografía y las mayúsculas |
Respuestas rápidas
¿Qué significa 'attempt to compare number with nil'?
Una línea compara un número con algo que no tiene valor, como price > 100 cuando price es nil. Encuentra qué variable es nil y por qué nunca se estableció.
¿Cómo doy a una variable un valor predeterminado en Lua?
Usa or: local count = tonumber(value) or 0. Si el valor es nil o no es un número, count se convierte en 0.
¿Por qué solo ocurre justo después de que me uno al servidor?
El script lee los datos del jugador antes de que el framework los haya cargado. Espera el evento jugador cargado, o verifica que el objeto jugador no sea nil antes de leerlo.


