table index is nil / index a nil value (field): FiveM Lua исправление

Исправить 'table index is nil' и 'attempt to index a nil value (field x)' в FiveM Lua: отсутствующие ключи конфиг, t[nil] присваивания, вложенные таблицы и безопасные шаблоны доступа.

Две ошибки, которые выглядят похожими, появляются всё время в скриптах 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')

Они означают разные вещи. Первое — о nil ключе, второе — о nil таблице. Оба сводятся к значению, которое ваш код ожидал и не нашёл. Это руководство показывает, как их различать и как написать доступ, чтобы он не мог аварийно завершиться.

table index is nil

Вы присвоили таблице, и ключ был nil:

lua
local cache = {}

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

Lua позволяет любое значение в качестве ключа, кроме nil (и NaN). Чтение cache[nil] просто даёт nil, но запись в него вызывает ошибку.

Найдите, какая переменная между скобками это nil на этой строке. Обычные источники:

  • Поиск игрока, который ничего не вернул. GetPlayerIdentifierByType(source, 'license') возвращает nil когда игрок не имеет идентификатора этого типа, например когда игрок не подключен через платформу, которую вы ожидаете.
  • Неправильный source. На сервере, проверьте, что событие действительно поступает от игрока. Вызов из консоли не имеет игрока позади.
  • Поле отсутствует в данных: data.id это nil потому что отправитель использовал data.Id.

Выведите это, чтобы быть уверенным:

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

Затем остановите присваивание, когда ключ отсутствует, и решите, является ли это ошибкой или нормальным случаем:

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

Здесь таблица отсутствует. Имя в скобках — это field, который был nil, и вещь, которую вы индексировали из неё находится на строке:

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

Lua называет то, что знает. Несколько форм, которые вы увидите:

Сообщение Значение
(global 'Config') Глобальная переменная Config это nil
(local 'data') Локальная переменная это nil, часто аргумент функции
(field 'shops') Config.shops это nil
(field '?') Таблица, найденная по ключу переменной, такой как Config.Shops[id], это nil
(upvalue 'cache') Переменная из внешней области это nil

Для field '?', Lua не может назвать ключ, потому что он вычисляется:

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

Исправление одинаково: найдите, какой шаг цепи это nil. Выведите каждый шаг:

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

Вложенные таблицы конфига

Большинство этих ошибок происходят из файлов конфига:

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

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

Если shopName это 'Bar' вместо 'bar', Config.Shops[shopName] это nil и следующий .items аварийно завершается. Причины для проверки:

  1. Другая орфография или регистр. Ключи Lua чувствительны к регистру.
  2. Файл конфига не загружен. Он должен быть в shared_scripts (или правильной стороне списка) fxmanifest.lua, перед файлом, который его читает.
  3. Конфиг определен только с одной стороны. Файл, указанный в server_scripts, невидим для клиента.
  4. Числовой ключ против строкового ключа. Config.Shops[1] и Config.Shops['1'] — разные записи. Это часто происходит после того, как данные проходят через JSON, см. FiveM json.decode errors.
lua
-- fxmanifest.lua
shared_scripts { 'config.lua' }
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }

Безопасные шаблоны доступа

Когда отсутствующее значение — это нормальный случай, напишите доступ, чтобы он его обработал.

Проверьте каждый шаг с 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)

Используйте or для значения по умолчанию:

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

Создайте небольшого помощника, когда вы часто читаете глубокие пути:

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

Внимание: не скрывайте каждый nil с помощью or {}. Если таблица, которая должна существовать, отсутствует, это ошибка в конфиге или порядке загрузки, и тихая резервная копия только перемещает ошибку куда-то менее очевидное. Используйте охранников для значений, которые могут быть отсутствующими.

Выведите таблицу, чтобы увидеть, что внутри

Когда вы не уверены, что содержит таблица, выведите её как JSON:

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

Вы увидите реальные ключи и заметите опечатку, другой регистр или число, где вы ожидали строку. Сделайте это в точке, где происходит ошибка, а не в верхней части файла, потому что данные могут быть заполнены позже.

Чеклист

Симптом Исправление
table index is nil Ключ в t[key] = value это nil; выведите его и вернитесь рано, если он отсутствует
attempt to index a nil value (field 'shops') Названное поле не устанавливается в таблице до него; проверьте имя и орфографию
attempt to index a nil value (field '?') Поиск с ключом переменной ничего не нашёл; проверьте ключ и его регистр
Работает на сервере, nil на клиенте Конфиг не в shared_scripts
Файл конфига проигнорирован Перечислите его перед файлами, которые его используют
Числовой ключ против строкового ключа [1] и ['1'] отличаются; преобразуйте с помощью tonumber или tostring

Для других частых сообщений nil см. attempt to compare nil и bad argument errors.

Короткие ответы

Что означает 'table index is nil'?

Скрипт попытался написать в таблицу, используя nil в качестве ключа, такой как t[key] = value когда key это nil. Lua не позволяет nil в качестве ключа, поэтому это останавливает.

Какова разница между 'table index is nil' и 'attempt to index a nil value'?

В 'table index is nil' ключ это nil. В 'attempt to index a nil value' сама таблица это nil, так что нет ничего для чтения или записи.

Почему ошибка говорит field '?' вместо имени?

Когда ключ — это переменная, такая как Config.Shops[id], Lua не может его назвать. Он показывает ?. Посмотрите на строку и найдите, какая часть цепи это nil.

Скрипты без этой проблемы

Shop CreatorМагазин меньше чем за минуту — владельцы, сотрудники, сейфы и ограбления в комплекте.Смотреть скрипт →Quest CreatorВизуальный редактор квестов и диалогов с NPC — узел за узлом прямо в игре.Смотреть скрипт →Item Creator V2Создавайте используемые предметы с анимациями, пропами, эффектами и не только — без кода.Смотреть скрипт →

Читайте также