tentar comparar número com nil / aritmética em um valor nil: corrigir
Corrija 'attempt to compare number with nil' e 'arithmetic on a nil value' no FiveM: dados do jogador não carregados, valores de config faltando, tonumber e padrões seguros com `or`.
Saída do console:
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')Uma linha do script usa um valor que ainda não existe em uma comparação ou um cálculo. Aqui está o que geralmente deixa o valor vazio, e como tornar o script seguro.
O que o erro significa
Lua lhe dá nil para qualquer variável ou entrada de tabela que não tem valor. Comparar (<, >, <=) ou calcular (+, -, *, /) com nil para o script com uma dessas mensagens:
attempt to compare number with nil(ouattempt to compare nil with number): um lado da comparação énil.attempt to perform arithmetic on a nil value: um cálculo usa uma variávelnil. Quando Lua conhece o nome, o adiciona, como(field 'money')ou(local 'price').
O número de linha na mensagem é a linha com a comparação ou a soma. O nil é um dos valores nessa linha. Imprima-os para ver qual é:
print('price', price, type(price))
print('count', count, type(count))
if price > count then
-- ...
end1. Os dados do jogador ainda não foram carregados
A causa mais comum: o script lê o jogador antes do framework ter terminado de carregá-los, por exemplo nas primeiras linhas de um arquivo, ou em uma thread que inicia imediatamente.
-- runs too early on the client: money is nil
local money = ESX.GetPlayerData().money
if money > 100 then
-- ...
endAguarde o evento de carregamento do framework e leia os dados de lá:
-- 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)No servidor, um objeto de jogador também pode ser nil quando o id está errado ou o jogador saiu. Verifique antes de usá-lo:
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return endlocal Player = QBCore.Functions.GetPlayer(source)
if not Player then return endNo QBox, o equivalente é exports.qbx_core:GetPlayer(source), com a mesma verificação nil.
Dica: se o script for reiniciado enquanto você estiver no servidor,
playerLoadedjá foi disparado e não disparará novamente. Leia os dados uma vez quando o recurso iniciar também.
2. Um valor de config está faltando
Você adicionou uma linha a config.lua que o script não tem, ou o script lê uma chave que seu config mais antigo não contém. Após uma atualização, um config.lua antigo é uma causa muito comum.
-- config.lua of the old version has no Config.Price
if playerMoney >= Config.Price then
-- ...
endCompare seu config com aquele enviado com a nova versão, e adicione as chaves faltando. Em seu próprio código, dê a cada configuração um padrão:
local price = Config.Price or 1003. O valor é uma string, não um número
Valores de um banco de dados, uma caixa de entrada em um menu ou uma mensagem JSON frequentemente chegam como texto. Comparar uma string com um número dá um erro diferente (attempt to compare number with string), mas uma conversão que falha dá este erro de novo. tonumber converte, e retorna nil quando não consegue:
local amount = tonumber(data.amount)
if not amount then
return -- not a number: stop here
end4. Use or para um padrão
or retorna o lado direito quando o lado esquerdo é nil (ou false). É a forma mais curta de tornar um cálculo seguro:
local count = tonumber(data.count) or 0
local total = (item.price or 0) * countUse-o onde um valor faltando realmente pode significar zero, como um bônus opcional. Onde um valor faltando é um bug, por exemplo um preço que deve existir, pare com uma mensagem clara em vez de ocultá-lo:
local price = Config.Items[name] and Config.Items[name].price
if not price then
print(('no price set for %s'):format(name))
return
end5. Um resultado de banco de dados ou callback está vazio
Uma consulta que não encontra linha dá nil ou uma tabela vazia. Ler uma coluna dela falha:
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
-- ...
endVerifique a linha primeiro:
local row = MySQL.single.await('SELECT balance FROM bank WHERE owner = ?', { identifier })
local balance = row and row.balance or 0O mesmo vai para callbacks de servidor: a resposta pode ser nil se o callback não foi encontrado ou retornou nada. Se seu script aguarda um callback, lide com esse caso. Relacionado: tentar chamar um valor nil é o erro irmão quando uma função, não um valor, está faltando.
6. Um erro de digitação em um nome de campo
xPlayer.money e xPlayer.Money são diferentes. Assim como price e Price. A mensagem de erro frequentemente nomeia o campo: verifique sua ortografia contra a documentação do framework ou contra a tabela que você imprime com print(json.encode(data)).
Checklist
| Sintoma | Correção |
|---|---|
| Erro logo após entrar | Aguarde o evento de jogador carregado antes de ler dados do jogador |
xPlayer ou Player é nil no servidor |
Verifique if not xPlayer then return end e a id de fonte |
| Erro após atualizar um script | Adicione as novas chaves do config.lua enviado ao seu |
| Valor vem de um menu ou JSON | Converta com tonumber(value) e verifique se não é nil |
| Um valor pode estar faltando intencionalmente | Use value or 0 como um padrão |
| Consulta de banco de dados retorna nada | Verifique se a linha não é nil antes de ler suas colunas |
| Campo é nulo mesmo que deveria existir | Verifique a ortografia e letras maiúsculas |
Respostas rápidas
O que significa 'attempt to compare number with nil'?
Uma linha compara um número com algo que não tem valor, como price > 100 quando price é nil. Encontre qual variável é nil e por que nunca foi definida.
Como dou a uma variável um valor padrão em Lua?
Use or: local count = tonumber(value) or 0. Se o valor é nil ou não é um número, count se torna 0.
Por que só acontece logo após entrar no servidor?
O script lê dados do jogador antes do framework tê-los carregado. Aguarde o evento de jogador carregado, ou verifique se o objeto do jogador não é nil antes de lê-lo.


