Skip to main content
TRACK B·LUA FUNDAMENTALS·Verified June 2026 · Lua 5.4 · ox_lib 3.x
Learning with an AI assistant?
Copies this lesson plus 2026 ground rules (no lua54 'yes', Cfx.re Portal, correct callback signatures) as a ready-to-paste mentor prompt.

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

You'll build
A calm way to read errors before you start changing random code.
Time
~18 minutes
You need
No setup. Read it before your first Lua lesson, then keep it bookmarked for later builds.
You'll learn
Read the first error -> spot nil -> spot wrong-side calls -> spot broken exports -> debug in a clean order
BEFORE YOU START

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.

Reading errors and fixing scripts, step by step.

Build it

Make the resource folder

The server has one folder for this lesson.

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:

text
resources/qu_debug_class

Create the files

Every file named in the manifest exists.

Create this exact file layout:

text
resources/qu_debug_class/
fxmanifest.lua
server.lua

Write fxmanifest.lua

FiveM knows which files to load.

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.

lua
fx_version 'cerulean'
game 'gta5'
 
server_script 'server.lua'

Break it on purpose

The resource contains one known nil bug.

Open server.lua and paste this. The variable player is nil because nothing ever filled it, so reading player.name is a nil error waiting to happen. This is the most common error you will ever see.

lua
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 command

Start it and trigger the error

The exact nil error appears in the console.

Open server.cfg and add this line:

text
ensure qu_debug_class

Save. Now open txAdmin in your browser (default address http://localhost:40120), log in, and open the Live Console from the left menu - that is where you type server commands and read this lesson's output. Run this there:

text
restart qu_debug_class

Now run the command:

text
debugclass

You 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

You know which of the four nil errors you have.

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:

text
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 value

Yours 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

The console proves player is nil before you change anything.

Before guessing, prove it. Add print(type(value), value) on the line before the crash. This one line answers almost every nil mystery. Edit server.lua to this:

lua
RegisterCommand('debugclass', function()
local player = nil
print('[qu_debug_class] type check', type(player), player)
print('[qu_debug_class] name is ' .. tostring(player and player.name))
end, true)

Then restart qu_debug_class and run debugclass again.

Fix the one thing and test again

The command prints a real name and no error.

The fix is to give player a real table with a name key, instead of nil. Change server.lua to this and restart cleanly:

lua
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

SymptomFix
Resource qu_debug_class does not existCheck the folder is inside resources and the ensure line uses the exact same name.
Could not load resource qu_debug_classOpen 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. Read the file path in the error: a server name called from a client/ file is a wrong-side call.
No such export in resource qb-core or ox_inventoryCheck the resource name, that it is started, and that you used the right framework snippet before rewriting any logic.
The command prints nothing in F8This 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.
  • Spot a wrong-side call by reading the file path (client/ vs server/) in the error.
  • Know that exports errors mean a resource is missing, misnamed, or not started, not that your logic is wrong.

Try it yourself