Harmony Mod Linter
Paste a Harmony/Oxide patch class and get flagged on the mistakes that break plugins silently — wrong Prefix/Postfix signatures, misspelled __instance, patch-order conflicts, missing unpatch-on-unload.
Input
Paste your patch class
Works on a single patch class or a whole plugin file. Nothing leaves your browser.
1 line(s).
Result
Nothing linted yet
Paste code on the left, or try the broken sample.
Findings
What might break, and why
Heuristic pattern matches only — not a compiler. Every result links to the Harmony/uMod doc it is based on.
Paste a patch class above, or load the broken sample, to lint it.
Every check below is a pattern match against the conventional Harmony/Oxide way of writing a patch class. Unconventional but valid code can trip these; take every result as "worth a second look," not a verdict.
A Prefix/Postfix/Transpiler/Finalizer is called by Harmony without an instance of your patch class. In the standard attribute-based pattern it must be static, or Harmony either skips it or throws at patch time.
Harmony: patching basics ↗A Prefix may return void or bool. Returning bool controls whether the original method still runs afterward. Any other return type is almost always leftover code or a copy-paste mistake — Harmony will throw at patch time.
Harmony: Prefix patches ↗A Postfix runs after the original method already executed, so returning false from one cannot stop it from running — that is a Prefix-only capability. (A bool return from Postfix is legitimate when it deliberately replaces the original's own bool return value — this check can misfire on that pattern.)
Harmony: Postfix patches ↗Harmony's special injected parameters are matched by exact name: __instance (two underscores, lowercase). One underscore, three underscores, or wrong casing means Harmony won't recognize it — the parameter silently receives its default value instead of an error.
Harmony: special parameters ↗A static method has no instance to inject. If the game method this patch targets is itself static, __instance is always null in this patch — only flagged when the target method's own declaration is also visible in the pasted code.
Harmony: special parameters ↗In a Prefix, __result must be declared "ref T __result" to change the original method's return value. Without ref it is just a local copy — the original still returns its own value.
Harmony: special parameters ↗A void method has no return value for Harmony to hand you. Declaring __result on a patch for a void target throws at patch time — only flagged when the target method's own declaration is also visible in the pasted code.
Harmony: special parameters ↗Harmony hands Prefix an uninitialized slot for __state so it can pass data forward to Postfix. The conventional (and compiler-friendliest) declaration is "out T __state".
Harmony: special parameters ↗The common pattern reads __state back in Postfix as "ref T __state" (or "in T __state" on newer Harmony). A plain value parameter can still work for read-only access in some versions — double check this one rather than trusting the warning outright.
Harmony: special parameters ↗A class with a Prefix/Postfix/Transpiler method but no [HarmonyPatch(...)] on the class is never wired up by PatchAll() — Harmony has no idea what method to patch, so it silently does nothing.
Harmony: annotations ↗[HarmonyPatch(typeof(X), "MethodName")] breaks silently the moment the game updates and that method is renamed or removed — the patch just never applies. [HarmonyPatch(typeof(X), nameof(X.MethodName))] fails to compile instead, which is far easier to catch.
Harmony: annotations ↗A Transpiler rewrites IL by returning a new instruction sequence. Anything other than IEnumerable<CodeInstruction> (or IEnumerable<CodeInstruction> via yield) is not a valid transpiler signature.
Harmony: transpilers ↗Two separate patch classes in this paste target the same type and method. Harmony does not guarantee which one runs first (or whether both survive) unless you set an explicit HarmonyPriority, or Before/After ordering, on both.
Harmony: annotations ↗Patches applied in Init()/Loaded() are not automatically removed when the plugin unloads or reloads. Without an Unload() that unpatches, every "oxide.reload" stacks a fresh copy of the same patches (or throws on the second PatchAll()).
uMod: writing plugins ↗An Unload() hook was found, but no call to UnpatchAll() / Unpatch(...) was found inside it. Patches applied via Harmony normally need to be explicitly removed there.
uMod: writing plugins ↗This looks like a full plugin class (it extends a plugin base class) that creates a Harmony instance, but no Init(), Loaded(), or OnServerInitialized() was found to call PatchAll() from. If that hook is just outside what you pasted, ignore this.
uMod: writing plugins ↗BasePlayer and BaseEntity parameters are frequently null in Rust hooks and patches (disconnects, environmental damage, destroyed entities). This flags the first use of such a parameter with a member access and no visible null check earlier in the method — guard clauses written a different way (helper methods, IsValid() checks, try/catch) will trip this without being a real bug.
uMod: Rust hook reference ↗Running your own game server?
Wespner game servers with DDoS protection, NVMe drives and activation within minutes.