Fix CS0051: Inconsistent accessibility in Oxide plugins
CS0051 means a public method, property or constructor exposes a type that is not public, so callers outside the assembly could not name the parameter. Change the nested type to public, or make the method private.
Error while compiling StatsApi: [1] Inconsistent accessibility: parameter type 'StatsApi.PlayerStats' is less accessible than method 'StatsApi.SaveStats(StatsApi.PlayerStats)' at 30:21
Why it happens
In C# an accessible member cannot advertise a parameter or return type that is less accessible than itself. Inside an Oxide plugin the usual trap is a nested helper class or struct (for example private class PlayerStats) while a matching method, property or constructor is declared public. StatsApi.SaveStats(StatsApi.PlayerStats) is public, but the nested PlayerStats type is private, so the compiler refuses with CS0051 and points at the method signature line. The same error appears when the nested type has no modifier at all: inside a class it defaults to private. A public property returning that nested type, or a public constructor taking it, triggers the identical message with property type or parameter type. Note that plugin classes themselves stay in the default internal visibility inside the Oxide.Plugins namespace; only the mismatch between two members' accessibility matters here.
How to fix it
- Read the message: it names both the member (
SaveStats) and the type (StatsApi.PlayerStats). - Open the plugin and find the nested type declaration.
- If code outside the plugin class never uses the type, add
privateorinternalto the method or property (or lower it to a private helper) so the member is no more accessible than the type. - If the method must stay public, mark the nested type
public(orinternal) so the accessibility matches:public class PlayerStats { ... }. - Fix every other member that mentions the same type, since the compiler reports them one by one.
- Save the file and run
oxide.reload StatsApi. Oxide compiles on save; a clean load printsLoaded plugin ...and noError while compilingblock. Insidenamespace Oxide.Pluginsthe typeTimeralready resolves without a using directive.
Before and after
using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
namespace Oxide.Plugins
{
[Info("StatsApi", "RustPluginGenerator", "1.0.0")]
[Description("Stores simple per-player statistics in oxide/data")]
public class StatsApi : RustPlugin
{
private StatsFile data;
private class StatsFile
{
public Dictionary<string, PlayerStats> Players = new Dictionary<string, PlayerStats>();
}
private class PlayerStats
{
public int Kills;
public int Deaths;
}
private void OnServerInitialized()
{
data = Interface.Oxide.DataFileSystem.ReadObject<StatsFile>(Name) ?? new StatsFile();
}
public void SaveStats(PlayerStats stats)
{
if (stats == null) return;
data.Players["last"] = stats;
Interface.Oxide.DataFileSystem.WriteObject(Name, data);
}
[ChatCommand("stats")]
private void CmdStats(BasePlayer player, string command, string[] args)
{
if (player == null) return;
PlayerStats stats;
if (!data.Players.TryGetValue(player.UserIDString, out stats))
{
stats = new PlayerStats();
data.Players[player.UserIDString] = stats;
}
stats.Kills++;
SaveStats(stats);
SendReply(player, "Kills: " + stats.Kills + ", Deaths: " + stats.Deaths);
}
}
}using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Plugins;
namespace Oxide.Plugins
{
[Info("StatsApi", "RustPluginGenerator", "1.0.0")]
[Description("Stores simple per-player statistics in oxide/data")]
public class StatsApi : RustPlugin
{
private StatsFile data;
private class StatsFile
{
public Dictionary<string, PlayerStats> Players = new Dictionary<string, PlayerStats>();
}
public class PlayerStats
{
public int Kills;
public int Deaths;
}
private void OnServerInitialized()
{
data = Interface.Oxide.DataFileSystem.ReadObject<StatsFile>(Name) ?? new StatsFile();
}
private void SaveStats(PlayerStats stats)
{
if (stats == null) return;
data.Players["last"] = stats;
Interface.Oxide.DataFileSystem.WriteObject(Name, data);
}
[ChatCommand("stats")]
private void CmdStats(BasePlayer player, string command, string[] args)
{
if (player == null) return;
PlayerStats stats;
if (!data.Players.TryGetValue(player.UserIDString, out stats))
{
stats = new PlayerStats();
data.Players[player.UserIDString] = stats;
}
stats.Kills++;
SaveStats(stats);
SendReply(player, "Kills: " + stats.Kills + ", Deaths: " + stats.Deaths);
}
}
}FAQ
Why does a nested class without any modifier cause CS0051?
Members of a class default to private, and that includes nested classes. A public method that takes that nested class as a parameter is more accessible than the type it exposes, so the compiler emits CS0051. Adding public to the nested class or private to the method resolves it.
Is this an Oxide or Carbon problem?
No. CS0051 is a plain C# compiler error produced by Roslyn. Oxide and Carbon only run the compiler and print its messages, which is why the fix is the same in both: align the accessibility of the member and the type it uses.
Do I need to make the plugin class public?
No. The plugin class itself is fine as declared. The mismatch is between the nested helper type and the member that exposes it. Changing the nested type to public or the member to private is enough; Oxide still finds the main class either way.
The error line number points to the method, not the class. Why?
The compiler reports the error where the inaccessible type is used in the signature, not where the type is declared. The message still names the type, so search the file for that name and adjust its declaration.
Different error?
Paste the full console output and get the cause and a fix in plain English.
Open the error explainerSkip the debugging
Generated plugins are compiled before you get them, and compiler errors are fixed automatically.
Generate a plugin2 free plugins a month, no card.
Last updated Oct 26, 2026.
Get plugins that compile first time
Generate