Skip to content
RustPluginGenerator

Rust Plugins Broken After Update: How to Fix Oxide and Carbon Plugins

After a monthly Rust update, plugins break because the game's code changed underneath them: members were renamed, types changed, or the method an Oxide hook patches was altered. Update Oxide or Carbon first, then read the compile errors, check which hooks changed, and fix or replace the plugins that still fail.

8 min readUpdated Oct 26, 2026

After a monthly Rust update, fix broken plugins in this order: install the Oxide or Carbon build that matches the new game version, restart, read the compile errors in the console, check which hooks changed, and then repair or replace each plugin that still fails. Most breakage falls into a small number of patterns, and each one is recognizable from the log.

Why plugins break after an update

Two separate things can go wrong, and they look different.

  • The plugin no longer compiles. The plugin references a class, field, method or type that Rust renamed, removed or changed. Oxide prints a compile error and skips that file. The other plugins still load.
  • The plugin compiles but does nothing, or throws at runtime. A hook's injection point moved or was removed, or the arguments it passes changed. The plugin loads normally but a feature is dead, or you get Failed to call hook messages.

Compile failures are loud and easy to find. Dead hooks are quiet, so you need to test features.

Step 1: Update Oxide or Carbon first

Before touching any plugin, update the framework. Oxide patches game methods to create hooks, so a build made for the previous Rust version can fail on the new one. Many "broken plugin" reports disappear once the framework matches the game.

  1. Update the Rust server through SteamCMD.
  2. Install the Oxide or Carbon release for that Rust version. See install Oxide on a Rust server and Oxide vs Carbon if you are choosing between them.
  3. Start the server and run oxide.version to confirm what is running.
  4. Run oxide.plugins to list which plugins loaded and which did not.

Carbon loads Oxide plugins and accepts the oxide.* commands, so the same workflow applies. Core framework updates often arrive a few hours to a day after the game update, so if no matching build exists yet, waiting is the correct fix.

Step 2: Read the compile errors

A failing plugin prints Error while compiling <PluginName>: followed by numbered messages in the form [1] <message> at <line>:<column>. The full text, including the CS code, is also written to oxide/logs (carbon/logs on Carbon). Start with the first error of each plugin, because later errors are often consequences of it.

ErrorTypical meaning after an update
CS1061A member you call no longer exists on that type, usually renamed or removed
CS0117A static member or enum value no longer exists
CS0029 / CS0266A type changed, so the value cannot be assigned as before
CS1503An argument type no longer matches a method parameter
CS1501 / CS7036A method gained or lost parameters
CS0246A type or namespace moved or was removed

Renamed or removed members: CS1061 and CS0117

When Rust renames a field or method, every plugin using the old name fails with CS1061 (instance members) or CS0117 (static members and enum values). The message names the type and the missing member, for example 'BasePlayer' does not contain a definition for 'oldName'.

The fix is to find what the member is called now (see step 4) and replace it. If the error mentions a generic constraint, the variant CS1061 with where clauses applies.

Type changes: CS0029 and NetworkableId

The best-known type change is entity IDs. net.ID is no longer a plain ulong; it is a NetworkableId struct, and the numeric value is read through net.ID.Value. Old code like this fails:

C#
ulong id = entity.net.ID;          // CS0029: cannot convert NetworkableId to ulong

The corrected version:

C#
ulong id = entity.net.ID.Value;

The same applies to comparisons and dictionary keys. If you store entity IDs in data files, store the ulong from .Value. See CS0029 NetworkableId for more cases.

Player IDs follow a similar pattern: player.userID converts implicitly to ulong, but when you need a real ulong value, for example for a method parameter or a dictionary key, use player.userID.Get(). A mismatch between ulong and string shows up as CS1503; use player.UserIDString where a string is required.

Signature changes: CS1501 and CS7036

If a game method gained a parameter, calls with the old argument list fail with CS1501 or CS7036. Add the new arguments, using the decompiler to see what they mean.

Step 3: Check removed or changed hooks

A plugin can compile and still lose a hook. Each month the updates page lists hooks that were added, removed or changed. Compare it against the hooks your plugins use.

What a change can look like:

  • A hook disappears. The method is never called. Features that depend on it silently stop.
  • The signature changes. Oxide only calls your method if every argument is an instance of the parameter type you declared. If a parameter type no longer matches what the hook passes, your method is skipped. Methods may declare fewer parameters than the hook passes, so trimming a parameter is sometimes enough.
  • The return behavior changes. Many hooks are patched so that any non-null return cancels the action, including false. Check the individual hook page, such as CanBuild or OnEntityTakeDamage, before assuming what a return value does.

If your console shows a deprecated hook warning, replace the hook now. It still works for the moment, but it is slated for removal. For background, read Oxide hooks explained.

To find dead hooks without reading the code, test each feature in-game after an update. A short checklist per plugin (run the command, take damage, loot a crate, build a structure) catches silent failures that logs never mention.

Step 4: Find the new API with a decompiler

Documentation lags behind the game. The reliable source is the game itself. The server's managed assemblies sit in RustDedicated_Data/Managed, mainly Assembly-CSharp.dll. Open it in a .NET decompiler such as ILSpy or dnSpy and look at the type from the error message.

A practical routine:

  1. Search for the type named in the error, for example BasePlayer.
  2. Look for members with similar names or the same type. Renames usually keep the type and behavior.
  3. If the member is gone, read the decompiled body of a related method to see how Rust now does it.
  4. For a changed signature, check the callers inside the game code to learn what the new arguments mean.
  5. Make the smallest change that compiles, then test the behavior.

Keep a decompiled copy of the previous version when you can. Comparing the old and new assemblies is much faster than searching blindly. See rust plugin development setup for configuring references in your editor.

Step 5: Reload one plugin at a time

You do not need a restart after each fix. Save the file in oxide/plugins and it reloads automatically, or run:

Text
oxide.reload MyPlugin

Watch for the Loaded plugin <Title> v<Version> by <Author> line. There is no separate "compiled successfully" message, so that line is your confirmation. After it appears, test the feature. For more on reading logs, see debugging Rust plugins.

Runtime errors after an update

If the plugin loads but throws, the log shows messages like Failed to call hook 'OnEntityTakeDamage' on plugin 'Name v1.0.0' (NullReferenceException: ...). After updates, these usually come from a value that used to be set and is now null, or a cast that no longer holds. See NullReferenceException in hooks and InvalidCastException in hooks.

Two other post-update patterns:

  • Old data files. Saved data containing entity IDs or removed item names can cause JSON reader errors or key lookups that fail. After a wipe, resetting the data file is often correct.
  • Removed items or prefabs. ItemManager.CreateByName returns null for an unknown shortname, and GameManager.server.CreateEntity can return null for a prefab path that no longer exists. Check both results.

Defensive patterns that survive updates

You cannot predict renames, but you can make plugins fail gently.

Null-check everything from the game. Hook arguments and nested members can be null more often after changes.

C#
private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info)
{
    if (entity == null || info == null) return null;
    var attacker = info.InitiatorPlayer;
    if (attacker == null) return null;
    return null;
}

Check item and prefab lookups.

C#
var item = ItemManager.CreateByName(config.RewardShortname, 1);
if (item == null)
{
    PrintWarning($"Unknown item shortname: {config.RewardShortname}");
    return;
}
player.GiveItem(item);

Put the warning in startup code or a rare path, never in frequently firing hooks such as damage or gather.

Keep game-specific values in config. Shortnames and prefab paths belong in the configuration file, so admins can correct them without editing code. See plugin config files.

Use the narrowest API. Prefer well-established members such as UserIDString, net.ID.Value and ShortPrefabName over internal fields, which change more often.

Isolate optional integrations. When calling another plugin through [PluginReference], always handle the reference being null, since the other plugin may be the one that broke. See calling other plugins.

What to do when a plugin is abandoned

If the author does not update and the fix is not small:

How this site re-checks its plugins each month

Plugins generated here follow strict rules so that they are easy to re-verify: only documented members, null checks on every hook parameter, no reflection and no reliance on private game fields. After each monthly Rust update, the hook signatures and game members used by our recipes are compared against the new game build. Hooks that were removed or changed are listed on the updates page, and affected recipes are corrected before the report goes out.

That does not replace testing on your own server. Your plugin mix, config and data files are unique, so run through the checklist below after each update.

Post-update checklist

  1. Update the server, then Oxide or Carbon, and confirm with oxide.version.
  2. Run oxide.plugins and note anything missing or failing.
  3. Fix compile errors one plugin at a time, first error first.
  4. Compare your plugins' hooks against the updates page.
  5. Test every feature in-game, especially anything driven by hooks.
  6. Clear or migrate data files that store entity IDs.
  7. Watch the console for the first hour for runtime errors and slow hook warnings (see performance).

On wipe day this runs together with the other tasks in the wipe day plugin checklist.

FAQ

Why do plugins break after a Rust update but not after a restart?

Plugins are compiled against the game's assemblies at load time. A Rust update replaces those assemblies, so code that referenced a renamed member or changed type no longer compiles. A plain restart changes nothing, which is why a plugin that worked yesterday can fail right after a forced wipe-day update.

Can a plugin load without errors and still be broken?

Yes. If Oxide's patch for a hook no longer applies, the hook silently never fires, or it fires with different arguments. The plugin loads and prints Loaded plugin, but its feature does nothing. Test every feature in-game after an update, not just the console output.

Do I need to recompile plugins manually?

No. Oxide and Carbon compile .cs files from the plugins folder at startup. To retry one plugin without restarting, run oxide.reload <Name>, or save the file again, since saving a file in the plugins folder triggers a reload.

Is it safe to run an old Oxide build on a new Rust version?

No. Oxide patches game methods, and a build made for an older game version can fail to apply patches or throw errors in core hooks. Install the Oxide or Carbon build released for your Rust version, and do not combine old builds with a new client or server branch.

What should I do when the plugin author has gone away?

Read the compile errors, fix the renamed members yourself if the changes are small, or regenerate a replacement with the plugin generator. Keep a copy of the original file so you can compare behavior. For larger plugins, consider splitting out the broken feature rather than rewriting everything.

Skip the C#: describe your plugin

Open generator