Skip to content
RustPluginGenerator
Runtime errorOxide + Carbon

Fix "Main plugin class should not have a constructor defined" (Oxide)

Oxide refuses to load a plugin whose main class declares a C# constructor. Remove the constructor and move the setup code into the Init or Loaded hook, then reload the plugin.

Server console
Main plugin class should not have a constructor defined: RaidAlerts

Why it happens

Oxide creates an instance of your RustPlugin class itself and manages the lifecycle through hooks. A user-defined constructor on the main plugin class fights that: the framework cannot guarantee field order, config, lang or permission state at construction time, so the loader rejects the class and prints Main plugin class should not have a constructor defined: <ClassName>. The usual trigger is code that was written like a normal C# service: a constructor that assigns config defaults, registers permissions, fills a message dictionary, starts a timer or calls Interface.Oxide APIs. All of those members exist on an Oxide plugin only after the instance is created, and the correct place for them is the Init hook (runs after the plugin instance exists, before config-dependent hooks like OnServerInitialized) or Loaded (runs after all plugins and config are ready). Nested helper classes may have constructors; only the class carrying [Info] must not.

How to fix it

  1. Find the constructor: a method with the same name as the class and no return type, e.g. public RaidAlerts() { ... }.
  2. Delete the constructor entirely, including its parameter list and braces.
  3. Move field initialization to the field declarations where possible (private int cooldown = 30;).
  4. Move runtime setup (permission registration, timer creation, reads of config/lang) into private void Init(), and anything that depends on other plugins or server state into private void Loaded().
  5. Save the file — Oxide recompiles automatically. The console should print Loaded plugin RaidAlerts v1.0.0 by RustPluginGenerator instead of the loader message.
  6. Run oxide.reload RaidAlerts to confirm, and check that the setup ran (permissions listed by oxide.show perms RaidAlerts).

Before and after

BeforeFails
using System.Collections.Generic;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("RaidAlerts", "RustPluginGenerator", "1.0.0")]
    [Description("Sends a chat message when a player joins the server")]
    public class RaidAlerts : RustPlugin
    {
        private const string PermUse = "raidalerts.use";
        private float cooldown;

        // Not allowed: Oxide creates the plugin instance itself.
        public RaidAlerts()
        {
            cooldown = 30f;
            permission.RegisterPermission(PermUse, this);
            Interface.Oxide.LogInfo("RaidAlerts setup complete");
        }

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Welcome"] = "Welcome {0}, read the rules before building."
            }, this);
        }

        private void OnPlayerConnected(BasePlayer player)
        {
            if (player == null || player.IsNpc)
            {
                return;
            }

            if (!permission.UserHasPermission(player.UserIDString, PermUse))
            {
                return;
            }

            player.ChatMessage(string.Format(lang.GetMessage("Welcome", this, player.UserIDString), player.displayName));
        }
    }
}
AfterFixed
using System.Collections.Generic;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("RaidAlerts", "RustPluginGenerator", "1.0.0")]
    [Description("Sends a chat message when a player joins the server")]
    public class RaidAlerts : RustPlugin
    {
        private const string PermUse = "raidalerts.use";
        private float cooldown = 30f;

        private void Init()
        {
            permission.RegisterPermission(PermUse, this);
            Interface.Oxide.LogInfo("RaidAlerts setup complete");
        }

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Welcome"] = "Welcome {0}, read the rules before building."
            }, this);
        }

        private void OnPlayerConnected(BasePlayer player)
        {
            if (player == null || player.IsNpc)
            {
                return;
            }

            if (!permission.UserHasPermission(player.UserIDString, PermUse))
            {
                return;
            }

            player.ChatMessage(string.Format(lang.GetMessage("Welcome", this, player.UserIDString), player.displayName));
        }
    }
}

FAQ

Can I have a constructor on a helper class inside the plugin?

Yes. The restriction applies only to the class that carries the [Info] attribute and derives from RustPlugin. Nested classes such as a config model or a data record can define constructors normally.

Where do I register permissions now?

In private void Init(). Call permission.RegisterPermission(...) there with a constant whose value starts with the lowercase class name, e.g. raidalerts.use. Do not register in OnServerInitialized, since that hook can run more than once across reloads of dependencies.

Does a static constructor also trigger this?

The message targets instance construction of the main plugin class. Static field initializers are fine, but avoid a static constructor that touches Oxide APIs, because it may run before the framework is ready. Keep such logic in Init.

Carbon loads the same file — will the fix work there too?

Yes. Carbon loads Oxide plugins and follows the same lifecycle, so moving setup into Init and Loaded is the correct pattern for both frameworks. The console folder differs (oxide/logs vs carbon/logs), but the source file is identical.

Different error?

Paste the full console output and get the cause and a fix in plain English.

Open the error explainer

Skip the debugging

Generated plugins are compiled before you get them, and compiler errors are fixed automatically.

Generate a plugin

2 free plugins a month, no card.

Last updated Oct 26, 2026.

Get plugins that compile first time

Generate