Versuche, Zahl mit nil zu vergleichen / Arithmetik mit nil: Behebung

Behebe 'attempt to compare number with nil' und 'arithmetic on a nil value' in FiveM: ungeladene Spielerdaten, fehlende Konfigurationswerte, tonumber und sichere Voreinstellungen mit `or`.

Konsolenausgabe:

text
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')

Eine Zeile des Skripts verwendet einen Wert, der noch nicht in einem Vergleich oder einer Berechnung existiert. Hier ist, was normalerweise den Wert leer lässt, und wie man das Skript sicher macht.

Was der Fehler bedeutet

Lua gibt dir nil für alle Variablen oder Tabelleneingaben, die keinen Wert haben. Das Vergleichen (<, >, <=) oder Berechnen (+, -, *, /) mit nil stoppt das Skript mit einer dieser Meldungen:

  • attempt to compare number with nil (oder attempt to compare nil with number): eine Seite des Vergleichs ist nil.
  • attempt to perform arithmetic on a nil value: eine Berechnung verwendet eine nil-Variable. Wenn Lua den Namen kennt, fügt es ihn hinzu, wie (field 'money') oder (local 'price').

Die Zeilennummer in der Meldung ist die Zeile mit dem Vergleich oder der Summe. Das nil ist einer der Werte auf dieser Zeile. Drucke sie aus, um zu sehen, welcher:

lua
print('price', price, type(price))
print('count', count, type(count))
if price > count then
    -- ...
end

1. Spielerdaten werden nicht geladen

Die häufigste Ursache: Das Skript liest den Spieler, bevor das Framework sie fertig geladen hat, zum Beispiel in den ersten Zeilen einer Datei, oder in einem Thread, der sofort startet.

lua
-- runs too early on the client: money is nil
local money = ESX.GetPlayerData().money
if money > 100 then
    -- ...
end

Warte auf das geladene Event des Frameworks und lies die Daten von dort:

lua
-- ESX client
local PlayerData = {}

RegisterNetEvent('esx:playerLoaded', function(xPlayer)
    PlayerData = xPlayer
end)
lua
-- QBCore client
local QBCore = exports['qb-core']:GetCoreObject()
local PlayerData = {}

RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
    PlayerData = QBCore.Functions.GetPlayerData()
end)

Auf dem Server kann ein Spieler-Objekt auch nil sein, wenn die ID falsch ist oder der Spieler gegangen ist. Überprüfe es, bevor du es verwendest:

lua
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return end
lua
local Player = QBCore.Functions.GetPlayer(source)
if not Player then return end

Auf QBox ist das Äquivalent exports.qbx_core:GetPlayer(source), mit der gleichen nil-Überprüfung.

Tipp: Wenn das Skript neu gestartet wird, während du auf dem Server bist, hat playerLoaded bereits ausgelöst und wird nicht wieder auslösen. Lies die Daten auch einmal, wenn die Ressource startet.

2. Ein Konfigurationswert fehlt

Du hast eine Zeile zu config.lua hinzugefügt, die das Skript nicht hat, oder das Skript liest einen Schlüssel, den deine ältere Config nicht enthält. Nach einem Update ist ein alter config.lua eine sehr häufige Ursache.

lua
-- config.lua of the old version has no Config.Price
if playerMoney >= Config.Price then
    -- ...
end

Vergleiche deine Config mit der, die mit der neuen Version versendet wird, und füge die fehlenden Schlüssel hinzu. In deinem eigenen Code gib jeder Einstellung eine Voreinstellung:

lua
local price = Config.Price or 100

3. Der Wert ist ein String, keine Zahl

Werte aus einer Datenbank, einer Eingabebox in einem Menü oder einer JSON-Nachricht kommen oft als Text an. Das Vergleichen eines Strings mit einer Zahl gibt einen anderen Fehler (attempt to compare number with string), aber eine Konvertierung, die schlägt fehl, gibt dir nil, das bringt diesen Fehler zurück. tonumber konvertiert und gibt nil zurück, wenn es nicht kann:

lua
local amount = tonumber(data.amount)
if not amount then
    return -- not a number: stop here
end

4. Verwende or für eine Voreinstellung

or gibt die rechte Seite zurück, wenn die linke Seite nil (oder false) ist. Es ist der kürzeste Weg, eine Berechnung sicher zu machen:

lua
local count = tonumber(data.count) or 0
local total = (item.price or 0) * count

Verwende es, wo ein fehlender Wert wirklich Null bedeuten kann, wie ein optionaler Bonus. Wo ein fehlender Wert ein Bug ist, zum Beispiel ein Preis, der existieren muss, stoppe mit einer klaren Nachricht, anstatt ihn zu verstecken:

lua
local price = Config.Items[name] and Config.Items[name].price
if not price then
    print(('no price set for %s'):format(name))
    return
end

5. Ein Datenbank- oder Callback-Ergebnis ist leer

Eine Abfrage, die keine Zeile findet, gibt nil oder eine leere Tabelle. Das Lesen einer Spalte davon schlägt fehl:

lua
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
    -- ...
end

Überprüfe die Zeile zuerst:

lua
local row = MySQL.single.await('SELECT balance FROM bank WHERE owner = ?', { identifier })
local balance = row and row.balance or 0

Das gleiche gilt für Server-Callbacks: Die Antwort kann nil sein, wenn der Callback nicht gefunden wurde oder nichts zurückgab. Wenn dein Skript auf einen Callback wartet, verwalte diesen Fall. Verwandt: attempt to call a nil value ist der Geschwister-Fehler, wenn eine Funktion, nicht ein Wert, fehlt.

6. Ein Tippfehler in einem Feldnamen

xPlayer.money und xPlayer.Money sind unterschiedlich. Das gleiche mit price und Price. Die Fehlermeldung nennt oft das Feld: überprüfe seine Rechtschreibung gegen die Framework-Dokumentation oder gegen die Tabelle, die du mit print(json.encode(data)) druckst.

Checkliste

Symptom Behebung
Fehler direkt nach dem Beitritt Warte auf das Spieler-geladenes Event, bevor du Spielerdaten liest
xPlayer oder Player ist nil auf dem Server Überprüfe if not xPlayer then return end und die Quell-ID
Fehler nach dem Aktualisieren eines Skripts Füge die neuen Schlüssel des versendeten config.lua zu deinem hinzu
Wert kommt von einem Menü oder JSON Konvertiere mit tonumber(value) und überprüfe, dass es nicht nil ist
Ein Wert kann absichtlich fehlen Verwende value or 0 als Voreinstellung
Datenbankabfrage gibt nichts zurück Überprüfe, dass die Zeile nicht nil ist, bevor du ihre Spalten liest
Feld ist nil, obwohl es existieren sollte Überprüfe die Rechtschreibung und Großbuchstaben

Kurze Antworten

Was bedeutet 'attempt to compare number with nil'?

Eine Zeile vergleicht eine Zahl mit etwas, das keinen Wert hat, wie price > 100, wenn price nil ist. Finde heraus, welche Variable nil ist und warum sie nie gesetzt wurde.

Wie gebe ich einer Variable einen Standardwert in Lua?

Verwende or: local count = tonumber(value) or 0. Wenn der Wert nil oder keine Zahl ist, wird count zu 0.

Warum passiert es nur direkt, nachdem ich dem Server beigetreten bin?

Das Skript liest Spielerdaten, bevor das Framework sie geladen hat. Warte auf das Spieler-geladenes Event oder überprüfe, dass das Spieler-Objekt nicht nil ist, bevor du davon liest.

Scripts ohne dieses Problem

Shop CreatorBau einen Shop in unter einer Minute — Besitzer, Angestellte, Tresore und Überfälle inklusive.Script ansehen →Pawn Shop AppEin Pfandmarkt zwischen Spielern, direkt in lb-phone.Script ansehen →Quest CreatorEin visueller Editor für Quests und NPC-Dialoge, Node für Node im Spiel gebaut.Script ansehen →

Weiterlesen