Debugging Your Mod
Practical debugging techniques — logging, data inspection, console commands, and solutions to the most common Lua errors.
When your mod doesn't work, you need to figure out why — fast. This guide covers the tools and techniques that will save you hours of staring at code.
Logging
Use log() with a severity level, tag, and message:
log('I', 'myMod', 'Player joined') -- Info
log('W', 'myMod', 'Config file missing') -- Warning
log('E', 'myMod', 'Failed to load save data') -- Error
log('D', 'myMod', 'State: ' .. dumps(state)) -- DebugLevels in order of severity: D (debug), I (info), W (warning), E (error).
Log output appears in the game console and in the log file at ~/AppData/Local/BeamNG.drive/latest.log (Windows).
print() vs log()
print() works but log() is preferred:
log()includes timestamp, level, and tag - easier to filterprint()has no level or tag - hard to find in noisy output- Use
print()only for quick throwaway debugging
Inspecting Data
dump()
Prints a table to the console with formatting:
local data = { score = 100, items = {"a", "b"} }
dump(data)dumps()
Returns a string representation (useful inside log()):
log('D', 'myMod', 'Vehicle data: ' .. dumps(vehicleData))Inspecting vehicle electrics
local veh = be:getPlayerVehicle(0)
veh:queueLuaCommand("dump(electrics.values)")Console Commands
Open the console with the ~ key (tilde). Useful commands:
- Type Lua directly to execute it in the GE context
extensions.load("mymod_feature")- load an extension manuallyextensions.unload("mymod_feature")- unload an extensiondump(extensions.mymod_feature)- inspect an extension's table
Common Errors
"attempt to index a nil value"
You are accessing a field on something that does not exist:
-- Error: veh is nil because no vehicle is spawned
local veh = be:getPlayerVehicle(0)
local name = veh:getName() -- crashes here
-- Fix: nil-check first
local veh = be:getPlayerVehicle(0)
if not veh then return end
local name = veh:getName()"attempt to call a nil value"
You are calling a function that does not exist:
-- Error: typo in function name
extensions.mymod_feature.doThng()
-- Fix: check the function name matches your extension
extensions.mymod_feature.doThing()Extension not loading
Common causes:
- File is not in the correct path (
lua/ge/extensions/for GE) - Filename does not match the extension name (underscores become dots in the name)
- Syntax error in the file - check the log for parse errors
- Missing
return Mat the end of the file
"attempt to call method using '.' (function expected, got nil)"
This usually means the extension table was not returned or the function was not added to M:
-- Wrong: function not exported on M
local function doThing() end
-- (missing M.doThing = doThing)
-- Right: function is local, then exported
local function doThing() end
M.doThing = doThingTips
- Keep a terminal open with
tail -fon the log file during development - Use descriptive tags in
log()so you can grep for your mod's output - Add
log('I', 'myMod', 'Extension loaded')toonInitto confirm loading - When debugging hooks, log the hook name and arguments to verify they fire
See Also
- Error Handling - pcall, nil safety, defensive patterns
- Hook Catalog - All available hooks
- Anti-Patterns - Common mistakes to avoid
- Performance - Avoiding performance issues
Input Bindings & Keybinding System
How to read, write, and capture keybindings — data structure, Lua and UI APIs, input capture flow, and critical cleanup for mod deactivation.
Data Persistence & Saving
How to save and load mod data — JSON files, game settings, career savedata, and persisting state across level changes.