<!-- fivemad.com, Markdown source of https://fivemad.com/docs/development/debugging -->
> Source: https://fivemad.com/docs/development/debugging
> Section: Development
> Tags: debugging, errors, SCRIPT ERROR, f8, console, print, nui_devtools, lua errors
> Last updated: 2026-09-22
> Site map for assistants: https://fivemad.com/llms.txt

# Debugging FiveM resources

Find and fix bugs in FiveM scripts: read SCRIPT ERROR lines, print and dump tables, the F8 and server consoles, NUI devtools, common Lua errors and a debugging routine.

Most FiveM bugs are found in minutes if you know where to look. This page is the routine: where errors show up, how to read them, how to narrow down a bug, and the errors you'll see most.

## Where output goes

| Output from | Shows in |
| --- | --- |
| Server scripts (`print`, errors) | The server console / txAdmin **Live Console**, and txAdmin's log files |
| Client scripts | The **F8** console in game, and `CitizenFX.log` in the FiveM application data `logs` folder |
| NUI JavaScript | NUI DevTools (`nui_devtools` in F8) |
| Resource start/stop messages | Server console |

Keep the F8 console and the Live Console open side by side while you test.

## Reading a script error

```text
SCRIPT ERROR: @my_shop/server/main.lua:42: attempt to perform arithmetic on a nil value (local 'price')
> handler (@my_shop/server/main.lua:42)
> fn (@ox_lib/imports/callback/server.lua:28)
```

- `@my_shop/server/main.lua:42`: resource, file, **line**. Go there first.
- `attempt to perform arithmetic on a nil value (local 'price')`: what went wrong and which variable. `price` is `nil` on line 42.
- The lines starting with `>` are the **stack trace**: how the code got there. Here an ox_lib callback called our handler.

Now ask: why is `price` nil? Usually a table lookup with a key that doesn't exist (`Config.Prices[item]` with a typo in `item`), or an argument the other side didn't send.

## Print debugging

Plain `print` is still the most used tool:

```lua
print('buy called', src, item, amount)
print(json.encode(data, { indent = true }))   -- dump a table
```

- `json.encode` turns tables into readable text. `print(someTable)` alone prints only `table: 0x...`.
- ox_lib has `lib.print.info(...)`, `lib.print.debug(...)` with log levels you can switch with a convar (`ox:printlevel`).
- Prefix your prints with the resource or function name so you can find them among other output.
- Remove debug prints (or put them behind a `Config.Debug` flag) before release. Spamming the console costs performance.

## A debugging routine

1. **Reproduce it.** Find the exact steps that trigger the bug.
2. **Read the first error**, not the last. Later errors are often side effects.
3. **Check which side** the problem is on: does the server get the event? Put a print at the top of the server handler. Does the client get the reply? Print in the client handler.
4. **Check the inputs**: print the arguments at the start of the function. Half of all bugs are "the value wasn't what I thought".
5. **Cut it in half**: comment out half of the suspicious code, see if the bug stays, repeat.
6. **Restart just your resource** (`ensure name`) instead of the whole server, it's faster. But if things behave oddly after many restarts, restart the server: some resources don't clean up on stop.
7. **Check the load order**: framework not started yet, dependency missing, `ensure` order in `server.cfg`.
8. **Change one thing at a time**, then test.

## The errors you'll see most

| Error | Usually means |
| --- | --- |
| `attempt to index a nil value (global 'QBCore')` / `'ESX'` / `'lib'` | You never got the framework or library object in this file or resource. Add `local QBCore = exports['qb-core']:GetCoreObject()`, `shared_script '@ox_lib/init.lua'`, or `@es_extended/imports.lua`. |
| `attempt to index a nil value (local 'Player')` | `GetPlayer(source)` returned nil: wrong `source` (used after a `Wait`), player not loaded yet, or the player left. Check before using. |
| `attempt to call a nil value (field 'X')` | Calling a function that doesn't exist: typo, wrong framework version, or a method renamed in an update. |
| `No such export X in resource Y` | Resource not started, wrong name, wrong side, or the export doesn't exist in that version. |
| `attempt to compare number with nil` | A value you compare is missing. Often a config key typo. |
| `bad argument #1 to 'X'` | Wrong type passed to a function or native (a string where a number is expected, a nil). |
| `Couldn't load resource X` | Manifest syntax error or missing file. |
| `SCRIPT ERROR ... stack overflow` | A function calls itself forever, or two events trigger each other. |
| `json.decode` error | The string isn't valid JSON, often an HTML error page from `PerformHttpRequest`. |
| Nothing happens, no error | The event isn't registered as a net event, the handler name has a typo, or the code never runs. Add a print at the entry point. |

## Client debugging tools

- **F8 console commands**: `resmon 1` (resource CPU and memory), `netgraph` (network graph), `cl_drawfps true`, `profiler record` (see [Threads and performance](/docs/development/threads-performance)).
- **`nui_devtools`**: Chrome DevTools for NUI. Your JavaScript errors and `console.log` appear there.
- **Draw it**: draw a marker or text at the coordinates your code uses, to see where it thinks things are.
- **Coordinates**: print `GetEntityCoords(PlayerPedId())` and `GetEntityHeading(PlayerPedId())` to grab positions for configs, or pick them on the [Interactive Map](/tools/interactive-map).

## Server debugging tools

- The txAdmin **Live Console** with search, and the log files in `txData`.
- `status` lists players and their IDs.
- `mysql_debug` and `mysql_slow_query_warning` convars for oxmysql.
- The server **profiler** (`profiler record 500` in the server console, then `profiler saveJSON file.json`) for slow ticks. Drop the file into the [Profiler Analyzer](/tools/profiler-analyzer) to see which resources use the most time.
- txAdmin's performance chart for hitches over time.

## Debugging streamed assets

- Missing model or texture: check the file is in `stream/`, the name matches exactly (case matters on Linux), and the resource is started. The [Vehicle Pack Validator](/tools/vehicle-pack-validator) checks a vehicle resource for broken links between metas, stream files and the manifest.
- A `data_file` path that doesn't match a file listed in `files` is silently ignored.
- Oversized asset warnings in the server console point to textures that need shrinking.

More in [Streaming custom assets](/docs/development/streaming-assets).

## Tools that make debugging easier

- The Lua Language Server in VS Code flags undefined globals and wrong argument counts **before** you run the code. See [Start developing](/docs/development#2-visual-studio-code).
- Git: `git diff` shows exactly what changed since it last worked. `git stash` lets you test the old version in seconds.

## Asking for help

When you're stuck, a good question gets an answer fast:

- What you're trying to do, in one sentence.
- The exact error text (copied, not a phone photo of the screen).
- The relevant code, formatted, with line numbers matching the error.
- What you already tried.
- Artifact build, framework and version.

Post it on [forum.cfx.re](https://forum.cfx.re) in the Development category or in the framework's Discord support channel.

Next: [Streaming custom assets](/docs/development/streaming-assets).
