attempt to call a nil value (field, global, method): cómo arreglarlo

¿Obteniendo 'attempt to call a nil value' en FiveM? Qué significan las variantes field, global y method, y cómo arreglar un error tipográfico, una exportación faltante o un error de colon versus punto.

En la consola:

text
SCRIPT ERROR: @my_script/server/main.lua:42: attempt to call a nil value (field 'GetPlayerFromId')
SCRIPT ERROR: @my_script/client/main.lua:17: attempt to call a nil value (global 'DrawText3D')
SCRIPT ERROR: @my_script/client/main.lua:63: attempt to call a nil value (method 'Notify')

Lua te dice que una línea intentó ejecutar una función que no existe. Este artículo explica las tres variantes, las causas habituales, y cómo arreglar cada una.

Qué significa el error

En Lua un nombre faltante no es un error en sí: leerlo da nil. El error solo aparece cuando pones paréntesis después de él, porque no puedes ejecutar nil. El texto dentro de paréntesis dice cómo el script alcanzó la función faltante:

  • attempt to call a nil value (global 'X'): una llamada simple como X(). La función no se define en ningún lugar que el script pueda ver.
  • attempt to call a nil value (field 'X'): una llamada a través de una tabla como ESX.X() o QBCore.Functions.X(). La tabla existe, pero no tiene una entrada nombrada X.
  • attempt to call a nil value (method 'X'): una llamada con dos puntos como obj:X(). El objeto existe, pero no tiene un método X.

El archivo y la línea frente al mensaje (@my_script/server/main.lua:42) es la línea que hace la llamada. Si no estás seguro de cómo leer el resto de la salida, ver cómo leer un error de script de FiveM.

1. Un error tipográfico en el nombre

Lua distingue mayúsculas y minúsculas. GetPlayerFromId y getPlayerFromId son dos nombres diferentes, al igual que TriggerClientEvent y TriggerclientEvent. Compara el nombre en el error con la documentación del framework, letra por letra.

2. La función no existe en tu versión

Los frameworks renombran y eliminan funciones. Esta es la causa más común en scripts que se escribieron para otra versión de tu framework.

lua
-- an old call that may be gone on your version
local xPlayer = ESX.GetPlayerFromId(source)
xPlayer.getInventoryItem('bread')

Verifica qué ofrece realmente tu framework. Imprime la tabla para ver sus entradas:

lua
for name, value in pairs(ESX) do
    print(name, type(value))
end

Si la función que necesitas no está en la lista, el script y el framework no coinciden. Actualiza el framework, actualiza el script, o reemplaza la llamada con la que tu versión tiene.

3. La exportación falta

Los exports son funciones que otro recurso proporciona. Cuando el recurso se detiene, no se inicia, o no exporta ese nombre, la llamada falla.

lua
local core = exports['qb-core']:GetCoreObject()
core.Functions.GetPlayer(source)

Si el recurso no se ejecuta, FiveM imprime No such export en su lugar. Si se ejecuta pero el nombre de exportación es incorrecto, puedes terminar con un field nil. Inicia el recurso primero en server.cfg, y verifica los nombres exactos de exportación en su documentación o fxmanifest.lua. Dos correcciones relacionadas: ESX is nil y No such export getSharedObject.

4. Colon versus punto

Un colon pasa el objeto como un argumento oculto primero. Un punto no. Mezclarlos da este error o argumentos incorrectos.

lua
-- calls the method with the object as first argument
player:Notify('hello')

-- calls a plain function stored in a table
Utils.Notify('hello')

Si el error dice (method 'Notify'), el objeto no tiene una entrada Notify: usa la forma de punto si la función vive en la tabla de la biblioteca, o verifica que el objeto sea realmente lo que crees que es. Con ox_lib, por ejemplo, lib.notify({...}) es una llamada de punto en la tabla lib.

5. La función se define más tarde o en otro archivo

Una función local debe definirse antes de la línea que la llama, en el mismo archivo. Una función definida en otro archivo solo es visible si es global, y solo si ese archivo se carga por el mismo lado (cliente o servidor) del mismo recurso.

lua
-- fails: DoThing is defined below the call
DoThing()

local function DoThing()
    print('hi')
end

Mueve la definición por encima de la llamada, o declárala primero con local DoThing y asígnala más tarde. Verifica también fxmanifest.lua: un archivo que no está enumerado en client_scripts, server_scripts o shared_scripts nunca se carga, así que sus funciones nunca existen.

lua
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }
shared_scripts { '@ox_lib/init.lua', 'config.lua' }

6. Una función del cliente usada en el servidor, o al revés

Muchos nativos y funciones del framework solo existen en un lado. PlayerPedId es solo cliente, y GetPlayerIdentifiers es solo servidor. Las tablas del framework también difieren: ESX.GetPlayerFromId es una función de servidor, mientras que el cliente usa ESX.GetPlayerData. Un script que se ejecuta en shared_scripts se ejecuta en ambos lados, así que una llamada que funciona en un lado se bloquea en el otro.

Consejo: la prueba más rápida es un print justo antes de la línea que falla: print(type(ESX.GetPlayerFromId)). Si imprime nil, la función falta. Si imprime function, el problema real está en otro lugar.

Guárdalo mientras depuras

Verifica antes de llamar, para que obtengas un mensaje claro en lugar de un bloqueo:

lua
local fn = ESX.GetPlayerFromId
if type(fn) ~= 'function' then
    print('GetPlayerFromId is missing: check the ESX version')
    return
end

No dejes guardas como esta en su lugar como la solución. Esconden el problema real, que es un script y un framework que no coinciden.

Lista de verificación

Síntoma Solución
(global 'X') La función no se define en el archivo o nunca se carga: verifica el manifiesto y el orden de definición
(field 'X') La tabla no tiene tal entrada: verifica la ortografía y la versión del framework
(method 'X') Objeto incorrecto o colon usado en lugar de punto: verifica qué contiene la variable
Funciona solo en un lado La función existe solo en cliente o solo en servidor
Error después de una actualización del framework Reemplaza la función eliminada con la nueva, o actualiza el script
La llamada de exportación retorna nil Inicia el recurso proveedor primero y verifica el nombre de exportación

Respuestas rápidas

¿Qué significa 'attempt to call a nil value'?

El script intentó ejecutar algo como una función, pero el nombre contiene nil, así que no hay nada para ejecutar. El nombre dentro de los paréntesis te dice qué función falta.

¿Cuál es la diferencia entre field, global y method en este error?

Un global es un nombre simple como Foo(), un field es una entrada de tabla como Config.Foo() o ESX.Foo(), y un method es una llamada con dos puntos como obj:Foo(). Solo te dice cómo se alcanzó la función faltante.

¿Puede una versión de framework incorrecta causarlo?

Sí. Un script escrito para una versión más antigua o más nueva de ESX, QBCore o QBox puede llamar a una función que tu versión renombró o eliminó, lo que deja nil atrás.

Scripts que evitan este problema

Advanced BoostingBoosting de vehículos desde una tablet: contratos de clase D a S+, crews y cola en vivo.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