Debug class for total beginners
This is the early primer shown before your first line of Lua on the scripts-from-zero path. Use it now for the error-reading habit, then revisit it later when exports, SQL, and framework errors become real in your own server. An error is a clue, not a verdict: Lua tried one specific thing, and one specific part was missing. You will build a tiny resource named qu_debug_class, break it on purpose, read the real error, and fix it with print(type(value), value).
Watch: debugging in action
Watch a real debugging pass first, reading the error, finding the line, and fixing one thing, then do the hands-on build below.
Build it
Make the resource folder
Inside your server's resources folder - the resources folder lives in your FXServer data/base folder, the same place that contains your server.cfg - create this folder:
resources/qu_debug_classCreate the files
Create this exact file layout:
resources/qu_debug_class/
fxmanifest.lua
server.luaWrite fxmanifest.lua
Open fxmanifest.lua and paste this. Lua 5.4 is the only runtime in 2026, so there is no lua54 line to add. Leave it out.
fx_version 'cerulean'
game 'gta5'
server_script 'server.lua'Break it on purpose
Open server.lua and paste this on your test server. The variable player is nil because nothing ever filled it, so reading player.name will produce a nil error when you run the command.
RegisterCommand('debugclass', function()
local player = nil
print('[qu_debug_class] name is ' .. player.name)
end, true) -- final `true` = restricted: only principals with ACE permission (e.g. the server console / admins) may run it, so a normal player cannot trigger this commandStart it and trigger the error
Open server.cfg and add this line:
ensure qu_debug_classSave. Open your server's txAdmin address, log in, and open the Live Console. The default http://localhost:40120 works when your browser is on the same machine as txAdmin; a remote VPS needs your configured administrator connection. Run these commands there, one at a time:
refresh
ensure qu_debug_classrefresh discovers the new resource and its manifest. ensure starts it, or restarts it if it is already running. Adding a line to server.cfg does not execute that line in a running server. Confirm there is no startup error before continuing. Now run the command:
debugclassYou will see a SCRIPT ERROR. Read only the first red line. It names the file (server.lua), the line number (3), and the missing thing (player).
Translate the error into plain English
nil means "there is nothing here." It becomes an error only when you use the nothing like it was real data or a real function. There are four you will meet constantly:
attempt to index a nil value -> you read thing.name on an empty thing
attempt to call a nil value -> you ran thing() but thing is not a function
attempt to concatenate a nil value -> you glued text onto an empty value
attempt to perform arithmetic on nil -> you did math (+ - * /) on an empty valueYours says index a nil value (local 'player'). So stop asking "why is Lua broken?" and ask "what value did I assume existed here?" The answer is player.
Confirm it with the fastest debug tool
Add print(type(player), player) immediately before the failing access. Keep the original access in place so you can see the diagnostic output followed by the same failure. Edit server.lua to this:
RegisterCommand('debugclass', function()
local player = nil
print('[qu_debug_class] type check', type(player), player)
print('[qu_debug_class] name is ' .. player.name)
end, true)Then restart qu_debug_class and run debugclass again.
Fix the one thing and test again
The fix is to give player a real table with a name key, instead of nil. Change server.lua to this and restart cleanly:
RegisterCommand('debugclass', function()
local player = { name = 'Los Santos' }
print('[qu_debug_class] type check', type(player), player)
print('[qu_debug_class] name is ' .. player.name)
end, true)Run restart qu_debug_class, then debugclass. No red line, and the name prints. You read the first error, found the file and line, named the missing value, proved it, and fixed exactly one thing.
If something went wrong
| Symptom | Fix |
|---|---|
Resource qu_debug_class does not exist | Check the folder is in the active server's resources directory and contains fxmanifest.lua. Run refresh, then ensure qu_debug_class. Keep the spelling identical; restart alone does not discover a new folder. |
Could not load resource qu_debug_class | Open fxmanifest.lua and fix the first quote, brace, or file name error the console reports. Do not add a lua54 line; it is deprecated and ignored. |
Failed to load script / unexpected symbol near '<eof>' | A syntax error: a missing end, quote, or bracket. Open the file and line the console names and balance the quotes, parentheses, and ends. |
attempt to call a nil value (global 'GetPlayerEndpoint') | That function is server-only. Check the named file's client_script, server_script or shared_script entry in fxmanifest.lua. The manifest determines where it runs; a filename alone does not. |
No such export in resource qb-core or ox_inventory | Check the resource name, startup status, export spelling, client/server side and the installed version's documented API. A started resource can still lack the export you called. |
The command prints nothing in F8 | This resource is a server_script. Because you triggered the command from the txAdmin Live Console, its output appears there, not in F8. (If you ever trigger a server command from in-game, FiveM may also mirror server output to your F8 console - but the server console is always the reliable place to read it.) |
What you can do now
- Read the first red error line and translate it into plain English before touching code.
- Tell the four nil errors apart: index, call, concatenate, and arithmetic.
- Use print(type(value), value) on the line before the crash to prove what is nil.
- Use the error's file path and the manifest to check whether the code runs on the client or server.
- Check resource startup, spelling, client/server side and API compatibility when an export is missing.
Try it yourself
Use the same method on your next error
Paste a sanitized first error into the free error decoder for a suggested investigation path, then check the named file and line yourself. It interprets text; it does not inspect your running server or prove that a proposed fix works. Record the command or player action, expected result, actual error and the single change you tested. Remove player identifiers, keys and connection strings before sharing an excerpt.
When you finish this exercise, run stop qu_debug_class and remove its ensure line from your test configuration if you do not need it to start again. Keep the two source files for practice.
