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

Corregir 'table index is nil' y 'attempt to index a nil value (field x)' en Lua de FiveM: claves de config faltantes, asignaciones t[nil], tablas anidadas y patrones de acceso seguro.

Dos errores que se ven parecidos surgen todo el tiempo en scripts de 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')

Significan cosas diferentes. El primero se trata de una clave nil, el segundo sobre una tabla nil. Ambos se reducen a un valor que tu código esperaba y no encontró. Esta guía muestra cómo distinguirlos y cómo escribir el acceso para que no pueda fallar.

table index is nil

Asignaste a una tabla, y la clave era nil:

lua
local cache = {}

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

Lua permite cualquier valor como clave excepto nil (y NaN). Leer cache[nil] solo da nil, pero escribir en ella lanza el error.

Encuentra qué variable entre los paréntesis es nil en esa línea. Las fuentes habituales:

  • Una búsqueda de jugador que no retornó nada. GetPlayerIdentifierByType(source, 'license') retorna nil cuando el jugador no tiene identificador de ese tipo, por ejemplo cuando el jugador no está conectado a través de la plataforma que esperas.
  • Un source incorrecto. En el servidor, verifica que el evento realmente viene de un jugador. Una llamada desde la consola no tiene jugador detrás.
  • Un campo faltante en los datos: data.id es nil porque el remitente usó data.Id.

Imprímelo para estar seguro:

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

Luego detén la asignación cuando la clave falta, y decide si eso es un error o un caso normal:

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

Aquí falta la tabla. El nombre entre paréntesis es el field que era nil, y la cosa que la indexaste está en la línea:

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

Lua nombra lo que sabe. Algunas formas que verás:

Mensaje Significado
(global 'Config') La variable global Config es nil
(local 'data') Una variable local es nil, a menudo un argumento de función
(field 'shops') Config.shops es nil
(field '?') Una tabla encontrada por una clave variable, como Config.Shops[id], es nil
(upvalue 'cache') Una variable de un alcance externo es nil

Para field '?', Lua no puede nombrar la clave porque se calcula:

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

La solución es la misma: encuentra qué paso de la cadena es nil. Imprime cada paso:

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

Tablas de config anidadas

La mayoría de estos errores provienen de archivos de configuración:

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

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

Si shopName es 'Bar' en lugar de 'bar', Config.Shops[shopName] es nil y el siguiente .items se bloquea. Causas a verificar:

  1. Diferente ortografía o caso. Las claves de Lua distinguen mayúsculas y minúsculas.
  2. El archivo de configuración no se carga. Debe estar en shared_scripts (o la lista del lado correcto) de fxmanifest.lua, antes que el archivo que lo lee.
  3. La config se define solo en un lado. Un archivo listado en server_scripts es invisible para el cliente.
  4. Una clave numérica contra una clave de cadena. Config.Shops[1] y Config.Shops['1'] son entradas diferentes. Esto a menudo sucede después de que los datos pasan a través de JSON, ver errores de FiveM json.decode.
lua
-- fxmanifest.lua
shared_scripts { 'config.lua' }
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }

Patrones de acceso seguro

Cuando un valor faltante es un caso normal, escribe el acceso para que lo maneje.

Verifica cada paso con 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)

Usa or para un valor predeterminado:

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

Haz un pequeño asistente cuando lees caminos profundos a menudo:

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

Cuidado: no ocultes cada nil con or {}. Si una tabla que debe existir falta, ese es un error en la config o el orden de carga, y un fallback silencioso solo mueve el error a algún lugar menos obvio. Usa guardias para valores que pueden estar legítimamente ausentes.

Vuelca una tabla para ver qué hay dentro

Cuando no estés seguro de lo que una tabla contiene, imprímela como JSON:

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

Verás las claves reales y detectarás un error tipográfico, un caso diferente o un número donde esperabas una cadena. Hazlo en el punto donde sucede el error, no al principio del archivo, porque los datos pueden llenarse después.

Lista de verificación

Síntoma Solución
table index is nil La clave en t[key] = value es nil; imprímela y retorna temprano si falta
attempt to index a nil value (field 'shops') El campo nombrado no se establece en la tabla antes de él; verifica el nombre y la ortografía
attempt to index a nil value (field '?') Una búsqueda con una clave variable no encontró nada; verifica la clave y su caso
Funciona en el servidor, nil en el cliente La config no está en shared_scripts
Archivo de config ignorado Enuméralo antes de los archivos que lo usan
Clave numérica vs clave de cadena [1] y ['1'] difieren; convierte con tonumber o tostring

Para los otros mensajes nil comunes, ver attempt to compare nil y errores de argumentos incorrectos.

Respuestas rápidas

¿Qué significa 'table index is nil'?

El script intentó escribir en una tabla usando nil como la clave, como t[key] = value cuando key es nil. Lua no permite nil como clave, así que se detiene.

¿Cuál es la diferencia entre 'table index is nil' y 'attempt to index a nil value'?

En 'table index is nil' la clave es nil. En 'attempt to index a nil value' la tabla en sí es nil, así que no hay nada para leer o escribir.

¿Por qué el error dice field '?' en lugar de un nombre?

Cuando la clave es una variable como Config.Shops[id], Lua no puede nombrarla. Muestra ?. Mira la línea y encuentra qué parte de la cadena es nil.

Scripts que evitan este problema

Shop CreatorCrea una tienda en menos de un minuto — dueños, empleados, caja fuerte y atracos.Ver script →Quest CreatorUn editor visual de misiones y diálogos con NPC, nodo a nodo dentro del juego.Ver script →Item Creator V2Crea items usables con animaciones, props, efectos y más — sin escribir código.Ver script →

Sigue leyendo