Skip to content
RustPluginGenerator
CS0029Oxide + Carbon

Fix CS0029: Cannot implicitly convert type 'NetworkableId' to 'uint' (Oxide)

Rust's BaseNetworkable.net.ID is now a NetworkableId struct, not a uint, so any code that assigns it to a uint or passes it where a uint is expected fails to compile. Use net.ID.Value, which is a ulong, instead.

Server console
Error while compiling EntityTracker:
[1] Cannot implicitly convert type 'NetworkableId' to 'uint' at 23:31

Why it happens

Facepunch replaced the plain integer network identifier on BaseNetworkable with the NetworkableId struct. Old plugin code and old snippets treat net.ID as a uint: storing it in a uint field, using it as a ulong without conversion, adding it to a string with a uint cast, or handing it to a method that expects uint. The compiler cannot convert the struct implicitly to a numeric type, so it reports CS0029 on the line where the assignment or argument happens. The same error appears in the reverse direction when you try to build a NetworkableId from a number directly. On Carbon the identical file fails the same way, because the Rust assembly types are the same; only the error formatting differs.

How to fix it

  1. Find every use of .net.ID in the plugin (search for net.ID).
  2. Append .Value to read the numeric id: ulong id = entity.net.ID.Value;.
  3. Store the value in a ulong, not a uint. Change field and local declarations accordingly.
  4. If you pass the id to a dictionary key or a HashSet<ulong>, the ulong from .Value already matches.
  5. If a method you call expects NetworkableId, pass entity.net.ID unchanged; do not construct it from a number.
  6. Save the file so Oxide recompiles, or run oxide.reload EntityTracker. The console should print Loaded plugin ... and no Error while compiling block; watch for any remaining CS error on the same line before assuming it is fixed.

Before and after

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

namespace Oxide.Plugins
{
    [Info("Entity Tracker", "RustPluginGenerator", "1.0.0")]
    [Description("Counts and remembers deployed entities by their network id")]
    public class EntityTracker : RustPlugin
    {
        private readonly Dictionary<uint, string> tracked = new Dictionary<uint, string>();

        private void OnServerInitialized()
        {
            int count = 0;
            foreach (var entity in BaseNetworkable.serverEntities)
            {
                if (entity == null || entity.ShortPrefabName == null)
                    continue;

                if (entity.ShortPrefabName.Contains("deployed"))
                {
                    uint id = entity.net.ID;
                    tracked[id] = entity.ShortPrefabName;
                    count++;
                }
            }

            Puts($"Tracked {count} deployed entities.");
        }

        private void OnEntitySpawned(BaseNetworkable entity)
        {
            if (entity == null || entity.ShortPrefabName == null)
                return;

            if (!entity.ShortPrefabName.Contains("deployed"))
                return;

            uint id = entity.net.ID;
            tracked[id] = entity.ShortPrefabName;
        }

        private void OnEntityKill(BaseNetworkable entity)
        {
            if (entity == null)
                return;

            uint id = entity.net.ID;
            tracked.Remove(id);
        }

        private void OnServerSave()
        {
            Puts($"Saving {tracked.Count} tracked entity ids.");
        }

        private void Unload()
        {
            tracked.Clear();
        }
    }
}
AfterFixed
using System.Linq;
using System.Collections.Generic;
using Oxide.Core;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Entity Tracker", "RustPluginGenerator", "1.0.0")]
    [Description("Counts and remembers deployed entities by their network id")]
    public class EntityTracker : RustPlugin
    {
        private readonly Dictionary<ulong, string> tracked = new Dictionary<ulong, string>();

        private void OnServerInitialized()
        {
            int count = 0;
            foreach (var entity in BaseNetworkable.serverEntities)
            {
                if (entity == null || entity.ShortPrefabName == null)
                    continue;

                if (entity.ShortPrefabName.Contains("deployed"))
                {
                    ulong id = entity.net.ID.Value;
                    tracked[id] = entity.ShortPrefabName;
                    count++;
                }
            }

            Puts($"Tracked {count} deployed entities.");
        }

        private void OnEntitySpawned(BaseNetworkable entity)
        {
            if (entity == null || entity.ShortPrefabName == null)
                return;

            if (!entity.ShortPrefabName.Contains("deployed"))
                return;

            ulong id = entity.net.ID.Value;
            tracked[id] = entity.ShortPrefabName;
        }

        private void OnEntityKill(BaseNetworkable entity)
        {
            if (entity == null)
                return;

            ulong id = entity.net.ID.Value;
            tracked.Remove(id);
        }

        private void OnServerSave()
        {
            Puts($"Saving {tracked.Count} tracked entity ids.");
        }

        private void Unload()
        {
            tracked.Clear();
        }
    }
}

FAQ

Is net.ID.Value stable across server restarts?

It is unique per spawned entity for the lifetime of that spawn and is safe as a session key. It is not a permanent identifier for a player-placed deployable; use the entity's OwnerID or your own saved data if you need something that survives restarts.

Why not just cast net.ID to uint?

A cast from the struct does not exist, so the compiler rejects it. Even if it worked, a uint cannot hold the full ulong range. Use .Value and keep the value as ulong.

The error points to a string concatenation, why?

Concatenating net.ID with a string picks up the same missing conversion. Use entity.net.ID.Value.ToString() or let the ulong concatenate, which works because ulong.ToString() exists.

Does Carbon show this error differently?

Carbon loads the same .cs file and hits the same Rust type, so the failure is identical. Carbon prints the message with its own format (often including the CS code); the fix is the same.

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