table index is nil / attempt to index a nil value (field): naprawa Lua FiveM

Napraw 'table index is nil' i 'attempt to index a nil value (field x)' w Lua FiveM – brakujące klucze config, przypisania t[nil], zagnieżdżone tabele i bezpieczne wzorce dostępu.

Dwa błędy, które wyglądają podobnie, pojawiają się cały czas w skryptach FiveM:

text
SCRIPT ERROR: @my_script/server/main.lua:42: table index is nil
SCRIPT ERROR: @my_script/client/main.lua:19: attempt to index a nil value (field 'shops')

Oznaczają różne rzeczy. Pierwsza dotyczy nil klucza, druga nil tabeli. Oba sprowadzają się do wartości, którą spodziewał się twój kod i nie znalazł. Ten przewodnik pokazuje, jak je rozróżnić i jak napisać dostęp, aby nie mógł się zawiesić.

table index is nil

Przypisałeś do tabeli, a klucz był nil:

lua
local cache = {}

local function remember(identifier, data)
    cache[identifier] = data     -- table index is nil when identifier is nil
end

Lua pozwala każdą wartość jako klucz, oprócz nil (i NaN). Czytanie cache[nil] po prostu daje nil, ale pisanie do niego podnosi błąd.

Znajdź, której zmiennej między nawiasami jest nil na tej linii. Zwyczajne źródła:

  • Szukanie gracza, które nic nie zwróciło. GetPlayerIdentifierByType(source, 'license') zwraca nil, gdy gracz nie ma identyfikatora tego typu, na przykład gdy gracz nie jest połączony przez platformę, którą oczekujesz.
  • Zły source. Na serwerze sprawdzaj, czy zdarzenie naprawdę pochodzi od gracza. Wezwanie z konsoli nie ma gracza za nim.
  • Pole brakujące w danych: data.id jest nil, ponieważ wysyłający użył data.Id.

Wydrukuj to, aby być pewnym:

lua
print('identifier', identifier, type(identifier))

Następnie zatrzymaj przypisanie, gdy klucz brakuje i zdecyduj, czy to błąd czy normalny przypadek:

lua
local function remember(identifier, data)
    if not identifier then
        return print('remember: no identifier, skipping')
    end
    cache[identifier] = data
end

attempt to index a nil value (field 'x')

text
attempt to index a nil value (field 'shops')

Tutaj tabela brakuje. Nazwa w nawiasach to pole, które było nil, a rzecz, którą go indeksowałeś, jest na linii:

lua
local first = Config.shops[1]    -- Config.shops is nil, so [1] fails

Lua wymienia to, co wie. Kilka form, które zobaczysz:

Wiadomość Znaczenie
(global 'Config') Zmienna globalna Config jest nil
(local 'data') Zmienna lokalna jest nil, często argument funkcji
(field 'shops') Config.shops jest nil
(field '?') Tabela znaleziona przez klucz zmiennej, takie jak Config.Shops[id], jest nil
(upvalue 'cache') Zmienna ze zewnętrznego zakresu jest nil

Dla field '?', Lua nie może nazwać klucza, ponieważ jest obliczony:

lua
Config.Shops[id].label          -- attempt to index a nil value (field '?')

Naprawa jest taka sama: znajdź, który krok łańcucha jest nil. Wydrukuj każdy krok:

lua
print(Config)
print(Config.Shops)
print(Config.Shops[id])

Zagnieżdżone tabele config

Większość tych błędów pochodzi z plików config:

lua
Config = {}
Config.Shops = {
    bar = { label = 'Bar', items = { 'beer', 'water' } },
}

-- somewhere else
local items = Config.Shops[shopName].items

Jeśli shopName to 'Bar' zamiast 'bar', Config.Shops[shopName] jest nil i dalsze .items zawali. Przyczyny do sprawdzenia:

  1. Inna pisownia lub wielkość liter. Klucze Lua są czułe na wielkość liter.
  2. Plik config nie jest załadowany. Musi być w shared_scripts (lub na właściwej liście boku) fxmanifest.lua, przed plikiem, który go czyta.
  3. Config jest zdefiniowany tylko po jednej stronie. Plik wymieniony pod server_scripts jest niewidoczny dla klienta.
  4. Klucz numeryczny względem klucza stringowego. Config.Shops[1] i Config.Shops['1'] to różne wpisy. Zdarza się to często, gdy dane przechodzą przez JSON, przeczytaj błędy json.decode FiveM.
lua
-- fxmanifest.lua
shared_scripts { 'config.lua' }
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }

Wzorce bezpiecznego dostępu

Gdy brakująca wartość jest normalnym przypadkiem, napisz dostęp, aby to obsługiwał.

Sprawdzaj każdy krok za pomocą and:

lua
local shop = Config.Shops and Config.Shops[shopName]
if not shop then
    return print(('Unknown shop: %s'):format(tostring(shopName)))
end
print(shop.label)

Używaj or dla domyślnego:

lua
local items = (shop and shop.items) or {}
local radius = Config.Radius or 5.0

Utwórz małego helpera, gdy często czytasz głębokie ścieżki:

lua
local function get(t, ...)
    for _, key in ipairs({ ... }) do
        if type(t) ~= 'table' then return nil end
        t = t[key]
    end
    return t
end

local label = get(Config, 'Shops', shopName, 'label')

Ostrzeżenie: nie ukrywaj każdego nil za pomocą or {}. Jeśli tabela, która musi istnieć, brakuje, to błąd w config lub kolejności ładowania i ciche fallback tylko przenosi błąd gdzieś mniej oczywisty. Używaj osłon dla wartości, które mogą być uzasadnione nieobecne.

Zrzuć tabelę, aby zobaczyć, co jest wewnątrz

Gdy nie jesteś pewien, co tabela zawiera, wydrukuj ją jako JSON:

lua
print(json.encode(Config.Shops, { indent = true }))

Zobaczysz rzeczywiste klucze i dostrzeżesz literówkę, inną wielkość liter lub liczbę, gdzie spodziewałeś się stringa. Zrób to w punkcie, gdzie błąd się zdarza, a nie na górze pliku, ponieważ dane mogą być wypełniane później.

Lista kontrolna

Objaw Naprawa
table index is nil Klucz w t[key] = value jest nil; wydrukuj go i wróć wcześnie, jeśli brakuje
attempt to index a nil value (field 'shops') Wymienione pole nie jest ustawione w tabeli przed nim; sprawdzaj nazwę i pisownię
attempt to index a nil value (field '?') Szukanie ze zmiennym kluczem nic nie znalazło; sprawdzaj klucz i jego wielkość liter
Działa na serwerze, nil na kliencie Config nie jest w shared_scripts
Plik config ignorowany Wymień go przed plikami, które go używają
Klucz liczbowy kontra klucz stringowy [1] i ['1'] różnią się; konwertuj za pomocą tonumber lub tostring

Aby uzyskać inne typowe wiadomości nil, przeczytaj attempt to compare nil i błędy złych argumentów.

Szybkie odpowiedzi

Co oznacza 'table index is nil'?

Skrypt próbował napisać do tabeli, używając nil jako klucza, takie jak t[key] = value, gdy key jest nil. Lua nie pozwala nil jako klucza, więc się zatrzymuje.

Jaka jest różnica między 'table index is nil' i 'attempt to index a nil value'?

W 'table index is nil' klucz jest nil. W 'attempt to index a nil value' sama tabela jest nil, więc nie ma niczego do przeczytania lub napisania.

Dlaczego błąd mówi pole '?' zamiast nazwy?

Gdy klucz to zmienna, taka jak Config.Shops[id], Lua nie może go nazwać. Pokazuje ?. Spójrz na linię i znajdź, która część łańcucha jest nil.

Skrypty bez tego problemu

Shop CreatorZbuduj sklep w niecałą minutę — właściciele, pracownicy, sejfy i napady w zestawie.Zobacz skrypt →Quest CreatorWizualny edytor questów i dialogów z NPC, budowanych węzeł po węźle w grze.Zobacz skrypt →Item Creator V2Twórz używalne przedmioty z animacjami, propami, efektami i nie tylko — bez pisania kodu.Zobacz skrypt →

Czytaj dalej