attempt to call a nil value (field, global, method): come ripararlo

Ottenendo 'attempt to call a nil value' in FiveM? Cosa significano le varianti field, global e method, e come riparare un errore di digitazione, un'esportazione mancante o un errore colon-versus-dot.

Nella console:

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 ti dice che una riga ha provato a eseguire una funzione che non esiste. Questo articolo spiega le tre varianti, le solite cause, e come risolvere ognuna.

Cosa significa l'errore

In Lua un nome mancante non è un errore di per sé: leggerlo dà nil. L'errore appare solo quando metti le parentesi dopo, perché non puoi eseguire nil. Il testo tra le parentesi dice come lo script ha raggiunto la funzione mancante:

  • attempt to call a nil value (global 'X'): una chiamata semplice come X(). La funzione non è definita da nessuna parte lo script possa vedere.
  • attempt to call a nil value (field 'X'): una chiamata attraverso una tabella come ESX.X() o QBCore.Functions.X(). La tabella esiste, ma non ha alcuna voce denominata X.
  • attempt to call a nil value (method 'X'): una chiamata con una virgola come obj:X(). L'oggetto esiste, ma non ha alcun metodo X.

Il file e la riga davanti al messaggio (@my_script/server/main.lua:42) è la riga che fa la chiamata. Se non sei sicuro di come leggere il resto dell'output, vedi how to read a FiveM script error.

1. Un errore di digitazione nel nome

Lua è sensibile alle maiuscole. GetPlayerFromId e getPlayerFromId sono due nomi diversi, così come TriggerClientEvent e TriggerclientEvent. Confronta il nome nell'errore con la documentazione del framework, lettera per lettera.

2. La funzione non esiste nella tua versione

I framework rinominano e rimuovono le funzioni. Questa è la causa più comune su script scritti per un'altra versione del tuo framework.

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

Controlla cosa offre davvero il tuo framework. Stampa la tabella per vedere le sue voci:

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

Se la funzione che hai bisogno non è nell'elenco, lo script e il framework non corrispondono. Aggiorna il framework, aggiorna lo script, o sostituisci la chiamata con quella che la tua versione ha.

3. L'esportazione è mancante

Le esportazioni sono funzioni che un'altra risorsa fornisce. Quando la risorsa è interrotta, non si è avviata, o non esporta quel nome, la chiamata fallisce.

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

Se la risorsa non è in esecuzione, FiveM stampa No such export al contrario. Se è in esecuzione ma il nome di esportazione è sbagliato, potresti finire con un field nil. Avvia la risorsa per prima in server.cfg, e controlla i nomi di esportazione esatti nella sua documentazione o fxmanifest.lua. Due correzioni correlate: ESX is nil e No such export getSharedObject.

4. Colon versus dot

Una virgola passa l'oggetto come primo argomento nascosto. Un punto non lo fa. Mescolarli dà questo errore o argomenti sbagliati.

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

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

Se l'errore dice (method 'Notify'), l'oggetto non ha alcuna voce Notify: usa la forma con il punto se la funzione vive sulla tabella della libreria, o controlla che l'oggetto sia davvero la cosa che credi. Con ox_lib, ad esempio, lib.notify({...}) è una chiamata con il punto sulla tabella lib.

5. La funzione è definita dopo o in un altro file

Una funzione locale deve essere definita prima della riga che la chiama, nello stesso file. Una funzione definita in un altro file è visibile solo se è globale, e solo se quel file è caricato dallo stesso lato (client o server) della stessa risorsa.

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

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

Sposta la definizione sopra la chiamata, o dichiara prima con local DoThing e assegnala in seguito. Controlla fxmanifest.lua anche: un file che non è elencato in client_scripts, server_scripts o shared_scripts non si carica mai, quindi le sue funzioni non esistono mai.

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

6. Una funzione client usata sul server, o al contrario

Molti nativi e funzioni framework esistono solo su un lato. PlayerPedId è solo client, e GetPlayerIdentifiers è solo server. Le tabelle framework differiscono anche: ESX.GetPlayerFromId è una funzione server, mentre il client usa ESX.GetPlayerData. Uno script che viene eseguito in shared_scripts viene eseguito su entrambi i lati, quindi una chiamata che funziona su un lato si arresta sull'altro.

Consiglio: il test più veloce è un print proprio prima della riga che fallisce: print(type(ESX.GetPlayerFromId)). Se stampa nil, la funzione è mancante. Se stampa function, il vero problema è da qualche altra parte.

Proteggilo mentre fai il debug

Controlla prima di chiamare, in modo da ottenere un messaggio chiaro invece di un arresto anomalo:

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

Non lasciare protezioni come questa in posizione come correzione. Nascondono il vero problema, che è uno script e un framework che non corrispondono.

Elenco di controllo

Sintomo Correzione
(global 'X') La funzione non è definita nel file o mai caricata: controlla il manifest e l'ordine di definizione
(field 'X') La tabella non ha tale voce: controlla l'ortografia e la versione del framework
(method 'X') Oggetto sbagliato o virgola usata al posto di un punto: controlla cosa contiene la variabile
Funziona solo su un lato La funzione esiste solo su client o solo su server
Errore dopo un aggiornamento di framework Sostituisci la funzione rimossa con quella nuova, o aggiorna lo script
La chiamata di esportazione restituisce nil Avvia la risorsa che fornisce per prima e controlla il nome di esportazione

Risposte rapide

Cosa significa 'attempt to call a nil value'?

Lo script ha provato a eseguire qualcosa come una funzione, ma il nome contiene nil, quindi non c'è nulla da eseguire. Il nome tra le parentesi ti dice quale funzione manca.

Qual è la differenza tra field, global e method in questo errore?

Un global è un nome semplice come Foo(), un field è una voce di tabella come Config.Foo() o ESX.Foo(), e un method è una chiamata con una virgola come obj:Foo(). Dice solo come la funzione mancante è stata raggiunta.

Una versione di framework errata può causarla?

Sì. Uno script scritto per una versione più vecchia o più recente di ESX, QBCore o QBox potrebbe chiamare una funzione che la tua versione ha rinominato o rimosso, il che lascia nil dietro.

Script senza questo problema

Advanced BoostingBoosting di veicoli dal tablet: contratti dalla classe D alla S+, crew e coda in tempo reale.Vedi script →Quest CreatorUn editor visuale di missioni e dialoghi con gli NPC, costruito nodo per nodo in gioco.Vedi script →Item Creator V2Crea oggetti utilizzabili con animazioni, props, effetti e altro — senza scrivere codice.Vedi script →

Continua a leggere