Skip to main content
TRACK B·PRODUCTION ENGINEERING·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.

Systematic debugging for production resources

Something will break. That is not a maybe, it is a certainty. The difference between a beginner and a developer is not that the developer writes perfect code. The difference is that the developer knows how to read the error, find the line, diagnose the category, and fix it calmly instead of changing code at random. This lesson teaches you that skill.

You'll ship
Structured logging in your scripts, a pcall wrapper for risky code, a repeatable read-locate-categorize-fix-test method, and the ability to read any FiveM error message.
Time
~40 minutes
You'll learn
Logging with tags, F8 vs server console, pcall for error recovery, stack traces, the fix-one-thing-and-test method, common error categories, and how to decode any FiveM error message.
Understand how FiveM errors actually work.
BEFORE YOU START

Build it

Make the resource folder

The server has one folder for this lesson.

Inside your server's resources folder, create this folder:

code
resources/qu_debugging_like_a_developer

Create the files

Every file named in the manifest exists.

Create this exact file layout:

code
resources/qu_debugging_like_a_developer/
fxmanifest.lua
client.lua

Write fxmanifest.lua

FiveM knows which files to load.

Open fxmanifest.lua and paste this:

code
fx_version 'cerulean'
game 'gta5'

client_script 'client.lua'

Older tutorials add a lua54 'yes' line here. As of June 2025 that setting is deprecated and ignored: Lua 5.4 is now the only Lua runtime, so you leave it out.

Write the lesson code

The topic is now represented by runnable code.

Open client.lua and paste this:

code
local function log(message)
print('[qu_debugging_like_a_developer] ' .. message)
end

local function risky()
error('planned failure')
end

RegisterCommand('debugfail', function()
local ok, result = pcall(risky)

if ok then
    log('risky() succeeded, returned: ' .. tostring(result))
else
    log('risky() failed, error was: ' .. tostring(result))
    log(debug.traceback('stack at point of failure', 2))
end
end, false)

Start and test it

The expected proof appears in the correct console.

Open server.cfg and add this line:

code
ensure qu_debugging_like_a_developer

Save. Because this folder is brand new, the running server does not know it exists yet, so run these two lines in the txAdmin Live Console, one at a time:

code
refresh
ensure qu_debugging_like_a_developer

refresh rescans the resources folder so the server discovers your new folder. ensure then starts it (and on later edits, ensure restarts it). Use restart qu_debugging_like_a_developer only after the resource has already been started once in this session.

Now join the server, press F8 to open the in-game console, and run the test there:

code
/debugfail

Because this is a client_script, the print lands in F8, not in txAdmin. You will see two lines:

The exact line number after client.lua: will match wherever the error(...) call sits in your file. In the code above that is line 6.

Keep reading the full lesson

Sign in to start, then unlock every step of this lesson and the full FiveM School with a membership.

Still ahead in this lesson
  • How it works
  • If something went wrong
  • What you can do now
  • Try it yourself

The remainder of Systematic debugging for production resources is available to FiveM School members.