Before a native run
Check the machine, the mod and your evidence rules before you start the real game.
When to use this
Before any run that starts Valheim or a dedicated server, so it neither hangs nor passes without proving anything. A mod can link here instead of copying these rules.
Steps
1. Check the machine
valheim-test env preflight
It checks this machine only and ends with ELIGIBLE or REFUSED and the reason. For a session on several machines, check its hosts instead:
valheim-test session check SESSION --hosts
It ends with READY or a REFUSED line per problem.
2. Leave the runtime to the toolkit
The runners enforce these rules; a hand-written driver must keep them itself.
| Rule | Why | Enforced by |
|---|---|---|
| A disposable profile per actor; the install is only read | A second process finds files locked and a preloader already running | Profiles and the host lock: one owned run per host |
BepInEx core, the plugins under test, an empty BepInEx/patchers |
A leftover preloader patcher breaks type loading before ValheimCLI listens | The patchers pin refuses any other folder |
Start the server executable, not start_headless_server |
The stock script drops extra arguments | GameLaunch.ForServer (launch) |
Pin the world; there is no -seed |
The server replaces a missing world with a new random one | The strict worlduid pin and WorldFixture |
| Devcommands on before joining | ValheimCLI refuses a mutating command, the join included, until then | SessionControl.Join through TestAccess |
| Join only once the server's game socket is open | It opens after location generation finishes; an earlier join times out | ClientRounds, or OwnedServerSession.WaitUntilJoinable in your own scenario |
| No teleport during the intro or within 2 s of a spawn or teleport | The game drops it silently | PlayerPlacement.Arrive (placing a player) |
| Your recent-servers list stays yours | The game adds every joined server to it | An owned client run moves it aside and puts it back |
To test a seed, create the world in a client and copy it in as a hashed fixture.
3. Check the mod
- Unpatch only your own Harmony id.
UnpatchAll()without an id removes every mod's patches and can leave saves incomplete. The log scan fails the run on it, but only at teardown. (Best-Practices) - Declare load order with
BepInDependency. A test adapter depends on ValheimCLI (valheimCLI.valheimCLI) and on the mod it tests. (example adapter) - Undo everything in
OnDestroyif the plugin is reloaded. The old assembly stays loaded, so leftover patches, handlers and objects run next to the new build. (what a plugin must undo, ReloadCheck) - Rebuild a mod that embeds ServerSync after a game update that touches it. An outdated copy shows as a black screen after connecting, or a
MissingFieldException. (Server-Troubleshooting)
4. Use a disposable character
- Local, never Steam Cloud. Tests change the character; a cloud copy carries that to every machine on the account.
valheim-teststages its own. - Cheat commands mark a character. Running a cheat records it in the save and blocks achievements for that character. Never use someone's own character. (Valheim-1.0-FAQ)
5. Decide what counts as evidence
- Wait for events, with timeouts that grow with the number of peers. A dedicated server sends object updates to one peer per frame, so each client lengthens replication (waiting).
- An error-free log proves nothing about spawns or events. A raid that never happens logs nothing; claim it only from a positive observation. (Spawning)
- Sample paint and height a metre inside each zone, not on the seam. A zone stores 65 samples per side, so the seam exists in both neighbours (ObserveCheck
paint). - Strict pins, one-shot mutations, incomplete is not zero, and one new output folder per attempt (reading results).
- Archive reports and logs by name. Never zip a run's output folder: it holds world copies, a server password and account identifiers.
Check the result
After the run:
valheim-test env status
The last line reads N runs ended and left nothing. Nothing was changed. If it lists your run, follow Clean up what a run left.
Problems
| Observation | Next check |
|---|---|
| Breakpoints are not hit | Attach the debugger after the main menu loads (Debugging-Plugins-via-IDE) |
| A development-build player will not attach | Match the game's Unity version, which BepInEx logs at startup |
| Timings do not match a player's game | Time a Release build |
| A rebuilt local package restores the old copy | Use a new NUGET_PACKAGES folder per run (local package feeds) |
dotnet run app.cs throws in JsonSerializer.Serialize(object) |
Add #:property PublishAot=false, or use JsonDocument |
Older wiki pages
Check these Valheim modding wiki pages' specifics against the current game.
| Page | What changed |
|---|---|
| RPC-System-Reference-Sheet | A routed RPC takes up to 6 parameters after the sender, not 4 |
| RPC-Method-registrations | Generated from an old game; regenerate names and hashes for the game you pin |
| ZDO-Hashes | Incomplete; the game keeps its keys in ZDOVars |
| Spawning, Event-System | Lists predate later biomes and world modifiers |
| Debugging-Plugins-via-IDE | Names Unity 2022.3; the game runs on Unity 6 |
| Custom-Item-and-Recipe-Creation, Custom-Language---Localization | Built on ValheimLib |
Related
- Debug a native run: read a failed run and clean up.
valheim-test: every command and option.