Debugging
Why a mod didn't load, the support report to send, the fault policy, crash reports, and breakpoints in a running server.
Start with kiln.log
kiln logs --mod my-mod, or read kiln/logs/kiln.log. A mod that didn’t load says why, and the others load anyway:
mod my-mod 0.1.0 loaded in … ms
[E] [host] mod my-mod 1.0.0 not loaded: missing dependency sample-lib ^1.0
[I] [host] mod my-mod 1.0.0 skipped: side 'client': not loaded on a server
Data packs log problems per file.
The mod list
echo mods > kiln/control/m.cmd writes each mod’s state, error, load order and cost to kiln/control/m.result.json.
kiln/logs/mods.txt always holds the current list. In code: Mods.All.
In the game, MODS in the main menu opens the mod manager: the mods of every framework (Kiln, EMF, EML, ShroudForge, SET, Greeneye and the rest) with their state and the reason, a search box and a Needs attention filter for mods that failed or are missing. See The Kiln menu. The launcher’s Logs page shows the same per framework, under Engines.
| State | Means |
|---|---|
| Loaded | running |
| Failed | couldn’t load; Error says why |
| Disabled | switched off after too many faults |
| Skipped | made for the other side, or switched off |
| Unloaded | on request |
Faults and crash reports
An exception escaping your code is a fault. Kiln logs it and carries on. After 5 in 60 seconds it disables the mod and writes a
crash report, and the server keeps running. Fix the cause, then reload <id>. Tune it in kiln/kiln.json:
{ "mods": { "fault_limit": 5, "fault_window_s": 60, "test_timeout_s": 30 } }
kiln/crash-reports/ also gets a report when an exception goes uncaught on another thread or native code faults. See them on the
launcher’s Logs page and the admin Crashes page.
Common causes
| Symptom | Likely cause |
|---|---|
| “wrong thread” | a service called from a timer or Task.Run; post back first |
| the server stutters | something blocks the tick thread |
| a content change isn’t reapplied at world load | made in OnLoad; use Content.OnReady |
| items disappear from saves | the item’s GUID changed |
| the old version runs after a reload | a thread, timer or static reference keeps it alive |
| a mod you extracted into the game folder doesn’t run | that framework’s drop-in switch is off for the profile. The list on the launcher’s Play shows the mod, marked Game folder, with Load them or Add it (Profiles and mods) |
an EML mod you added is missing while EML’s own dbghelp.dll is installed |
the launcher copies it into mods/ when it sets up the profile. Start once from the launcher’s Play (Your other loader is installed too) |
| an EML mod doesn’t apply while a ShroudForge mod is on | ShroudForge runs an EML mod only when its own switch for it is on. The launcher and the in-game Mods menu say why it doesn’t run, and suggest a switch where one helps (EML and ShroudForge together) |
| none of ShroudForge’s data mods apply | one EML mod failed inside ShroudForge, and ShroudForge dropped its whole startup pass. The in-game Mods menu shows them as failed; the launcher’s Engines view can still say they run |
| the in-game Mods page is empty next to ReShade or another overlay | since dev.24 Kiln takes the graphics device over when the game makes its swapchain, if the PC has one graphics device. When it can’t, kiln.log says why |
| Steam shows the game as running for about a minute after you quit (Linux) | Steam’s networking library crashes while the game shuts down, and the system writes a crash dump of several gigabytes. No Kiln or mod code is in that crash |
a .rar is refused |
no unrar, 7-Zip or bsdtar on the PC. Extract it and drop the folder |
Save a support report
When mods don’t load and the log doesn’t say why, save a report. One zip answers what a maintainer would otherwise ask over several posts: which Kiln, which OS and Proton, which game build, what is in the game folder, what the profile loads and what the last start did. If you help someone, ask them to send that zip.
- Launcher: the Logs page, Support report above the tabs, then Save report. It asks where to put
kiln-report-<date>.zip. Copy summary copies a few lines for a forum post. It works with no game found yet, and on a server’s Logs page. - Servers and manual installs:
kilnctl report [NAME] [--dir D] [--out FILE] [--print].NAMEis a server instance,--dira server or game folder. With neither it uses the game Steam knows.--printwrites the summary to the terminal instead of a zip.
It only reads. Nothing is written to the game folder, and the game may be running.
In the zip:
summary.txt: the findings in plain sentences (for example “3 mods in the game folder are not loaded by the profile ‘My mods’”, with the fix), then the system, the game, Kiln in the game, the profile and the last start;report.json: the same findings for tools;- the end of
kiln.log,proxy.logandeml.log, and the newest crash report; - Kiln’s state files, and
profile.json,chain.iniandkiln.jsonas they are, after the removals below; - the launcher’s log;
- lists of the game folder, Kiln’s folder and each framework’s mods folder: names, sizes and dates only.
The zip is usually under 1 MiB, and cut at 6 MiB before compression.
Removed from every text: your user name, your home folder, the machine name, Steam account names and ids, and IP addresses (except your own machine’s 127.x). In JSON, values of fields named like a secret or an address (token, password, key, cookie, host and similar) are replaced.
Never read: saves and world data, mod settings (kiln/config, including network.json), the admin pages’ data, the
contents of any mod (only names, sizes and dates), and Steam’s files except the name of the compatibility tool, your
launch options and the account names it needs to remove. summary.txt ends with this list.
Read summary.txt before you post it. A character or server name you chose can appear in a log line, and the report
can’t recognise that.
If something is broken, the report still works: no Kiln, no game folder, a damaged profile or an unreadable file become lines under “Not readable”, and the rest is written. Tested with unit tests and the launcher’s own tests; a report made on a real Windows PC or Steam Deck is not checked yet.
Hooks and other DLLs
When a feature stops working next to another DLL mod, check the hook lines in kiln.log (new in dev.21):
[kiln] hooks: chat/ChatLogAdd chained over enshwick.dll+0x11ea80
[kiln] hooks: xhl.dll+0x4410 hooked over Kiln's chat/ChatLogAdd (Kiln's detour stays armed; it is reached through their jump)
[W] [kiln] compat: overlap: xhl-core.dll+0x11ea80 hooked chat/ChatLogAdd before chat, emf; Kiln chained over it. ...
kiln/state/hooks.json lists every hooked function, its links in order, overlaps and the compat rules that fired. The
fix for an overlap is usually to load the other DLL late:
closed-source DLL mods. For your own hooks: Hooks and patches.
Breakpoints
kiln debug attaches netcoredbg to the mods in a running local server: breakpoints, stack,
locals, watches, stepping.
A breakpoint pauses the whole server, for everyone on it. Debug on a test server.
VS Code bundles the debugger. For another editor:
- Get netcoredbg’s win64 build (tested: 3.2.0-1092), even on Linux. Put
netcoredbg.exeintools/netcoredbg/in Kiln’s data folder, or setKILN_NETCOREDBG. - Deploy a Debug build, so its
.pdbgoes along:kiln deploy --reload. - Start the server:
kiln run --server <name>. - Use
kiln debug --server <name> --dapas your debug adapter, and send anattachwith noprocessId.
kiln debug --server <name> alone shows what it would run. Debug on the machine that built the mod: breakpoints match the
.pdb’s paths.
Disconnecting or closing your editor never ends the server, and a server in a Steam library is always refused. These can still hurt:
- killing netcoredbg while attached ends the server with no save: disconnect instead;
- a mod that leaks its old copy can make breakpoints miss and a disconnect end the server.
kiln debugwarns; restart first; - watch expressions run in the server.
After kiln reload, disconnect and attach again.
Tested on dedicated servers under Linux and Wine. Windows servers are untested, and the game client isn’t covered.