Debugging your first mod
Status: Partly implemented. The log, the Mods screen,
clight check, hot reload and/clight reload-configwork. Debugger attach, in-game inspection commands andclight testare Planned.
1. Read the log
Everything a mod logs goes to the game’s logs/latest.log (in the instance folder when you use the launcher), prefixed with the mod id:
[12:00:01] [main/INFO] [ruby_lua] Ruby (Lua) 1.0.0 loaded
[12:00:07] [Server thread/ERROR] [ruby_lua] scripts/main.lua:42: attempt to index a nil value (local 'p')
How to write to it:
| Language | Call |
|---|---|
| Lua | cl.log("Hello", player.name), cl.log.warn("%d left", n), or plain print(...) |
| C | CL_LOG("%d rubies", n), CL_LOGF(CL_LOG_WARN, ...), or cl_log(CL_LOG_INFO, CL_STR("text")) |
| C++ | clight::log::info("{} rubies", n) (warn, error, debug) |
C and C++ printf / stdout and stderr also land in the log (WASI output is routed there).
Lua errors carry the file, line and a traceback. A WebAssembly trap is logged with the function names when the module was built in dev mode (clight build without --release keeps debug info).
2. In-game tools
| Tool | Shows |
|---|---|
| Mods screen (title screen or pause menu → Mods) | Every mod with its state and load error (CLL-xxxx codes, see Error codes), its permissions and its config page |
/clight reload-config (operators) |
Reads every mod’s config files again |
| Hot reload | Under clight run, saving a Lua script reloads it within a second. A reload that fails keeps the old code running and logs why. |
Planned: per-mod timings, /clight mods, /clight events <name> and a trace of event dispatch.
3. Debuggers
Planned. Until then, log what you need, and keep handlers small so the log line points at the problem. In Lua, cl.inspect(value) turns a table into readable text for the log.
4. Common first problems
| Symptom | Cause | Fix |
|---|---|---|
| The mod isn’t on the Mods screen | The .clmod or folder is not in this game’s mods/ (with the launcher: the instance’s folder), or it is named .clmod.disabled |
Check the folder; clight check the package |
CLL-1002 on load |
A manifest field is missing or wrong | clight check names the field |
CLL-2004 on load |
The mod was built for an older API major | Update "api" and rebuild |
| The item shows as a purple/black cube | No item model definition | Add assets/<ns>/items/<path>.json |
The name shows item.ruby_lua.ruby |
Missing lang key | Add it to assets/<ns>/lang/en_us.json |
wrong_phase / CL_E_WRONG_PHASE on register |
Registering outside lifecycle.register |
Move the registration into the register handler |
| Handler never called | The event belongs to the other side (a server event in a client-only mod), or a filter doesn’t match | Check the event’s side in Complete event list |
| A newer function is missing at run time | The game is older than the API minor you used | Test with cl.has("name") / cl_core_has first |
5. Tests
clight test with scripted fake players is Planned. Today: try the mod with clight run, and for servers start a local Celestial server with the mod in its mods/ folder.