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:
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:
local cache = {}
local function remember(identifier, data)
cache[identifier] = data -- table index is nil when identifier is nil
endLua позволяет любое значение в качестве ключа, кроме nil (и NaN). Чтение cache[nil] просто даёт nil, но запись в него вызывает ошибку.
Найдите, какая переменная между скобками это nil на этой строке. Обычные источники:
- Поиск игрока, который ничего не вернул.
GetPlayerIdentifierByType(source, 'license')возвращаетnilкогда игрок не имеет идентификатора этого типа, например когда игрок не подключен через платформу, которую вы ожидаете. - Неправильный
source. На сервере, проверьте, что событие действительно поступает от игрока. Вызов из консоли не имеет игрока позади. - Поле отсутствует в данных:
data.idэто nil потому что отправитель использовалdata.Id.
Выведите это, чтобы быть уверенным:
print('identifier', identifier, type(identifier))Затем остановите присваивание, когда ключ отсутствует, и решите, является ли это ошибкой или нормальным случаем:
local function remember(identifier, data)
if not identifier then
return print('remember: no identifier, skipping')
end
cache[identifier] = data
endattempt to index a nil value (field 'x')
attempt to index a nil value (field 'shops')Здесь таблица отсутствует. Имя в скобках — это field, который был nil, и вещь, которую вы индексировали из неё находится на строке:
local first = Config.shops[1] -- Config.shops is nil, so [1] failsLua называет то, что знает. Несколько форм, которые вы увидите:
| Сообщение | Значение |
|---|---|
(global 'Config') |
Глобальная переменная Config это nil |
(local 'data') |
Локальная переменная это nil, часто аргумент функции |
(field 'shops') |
Config.shops это nil |
(field '?') |
Таблица, найденная по ключу переменной, такой как Config.Shops[id], это nil |
(upvalue 'cache') |
Переменная из внешней области это nil |
Для field '?', Lua не может назвать ключ, потому что он вычисляется:
Config.Shops[id].label -- attempt to index a nil value (field '?')Исправление одинаково: найдите, какой шаг цепи это nil. Выведите каждый шаг:
print(Config)
print(Config.Shops)
print(Config.Shops[id])Вложенные таблицы конфига
Большинство этих ошибок происходят из файлов конфига:
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 аварийно завершается. Причины для проверки:
- Другая орфография или регистр. Ключи Lua чувствительны к регистру.
- Файл конфига не загружен. Он должен быть в
shared_scripts(или правильной стороне списка)fxmanifest.lua, перед файлом, который его читает. - Конфиг определен только с одной стороны. Файл, указанный в
server_scripts, невидим для клиента. - Числовой ключ против строкового ключа.
Config.Shops[1]иConfig.Shops['1']— разные записи. Это часто происходит после того, как данные проходят через JSON, см. FiveM json.decode errors.
-- fxmanifest.lua
shared_scripts { 'config.lua' }
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }Безопасные шаблоны доступа
Когда отсутствующее значение — это нормальный случай, напишите доступ, чтобы он его обработал.
Проверьте каждый шаг с and:
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 для значения по умолчанию:
local items = (shop and shop.items) or {}
local radius = Config.Radius or 5.0Создайте небольшого помощника, когда вы часто читаете глубокие пути:
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:
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Создавайте используемые предметы с анимациями, пропами, эффектами и не только — без кода.Смотреть скрипт →