Fix "Failed to call hook 'OnEntityDeath'" NullReferenceException in Oxide plugins
A hook method touched a null member, usually because HitInfo or HitInfo.InitiatorPlayer is null. OnEntityDeath fires for every death, including bleed outs, fall damage and decay, where info is null. Null-check the parameters and the attacker before using them.
Failed to call hook 'OnEntityDeath' on plugin 'KillRewards v1.0.0' (NullReferenceException: Object reference not set to an instance of an object) at Oxide.Plugins.KillRewards.OnEntityDeath (BaseCombatEntity entity, HitInfo info) [0x0001c] in <8f3c1a2b4d5e4f6a9b0c1d2e3f4a5b6c>:0
Why it happens
Oxide calls OnEntityDeath for every BaseCombatEntity that dies, and the HitInfo passed in reflects the killing blow. That HitInfo is null when there is no attacker context, for example when an entity dies from decay, radiation, suffocation or starvation, or when the server constructs the death itself. Even when info is present, info.InitiatorPlayer is null for deaths caused by non-player sources: fall damage, fire that propagated, animals, NPCs, turrets, or another entity dying nearby. Code that assumes info.InitiatorPlayer is a live BasePlayer and immediately reads displayName, UserIDString, inventory or GetActiveItem will throw NullReferenceException on the first such death. The plugin stays loaded and the hook keeps being called, so the console fills with one stack trace per death until the method guards every dereference.
How to fix it
- Open the method named in the stack trace (here
OnEntityDeath) and list every member you read frominfo,entityandinfo.InitiatorPlayer. - Return early when
infois null, then wheninfo.InitiatorPlayeris null, before touching anything on the player. Also guardentityif you use it. - Separately handle
info.Initiatorwhen you care about non-player killers; useInitiatorPlayeronly for the reward path. - Check
entity.IsDestroyedif you read the victim after the death, because cleanup can run later. - Save the file and reload with
oxide.reload KillRewards; a clean load printsLoaded plugin KillRewards v1.0.0 by RustPluginGenerator. - Kill a player via
killin the server console and let another die from fall damage; the console should show noFailed to call hookline.
Before and after
using System.Collections.Generic;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("KillRewards", "RustPluginGenerator", "1.0.0")]
[Description("Gives a small cash reward for player kills.")]
public class KillRewards : RustPlugin
{
private const string PermUse = "killrewards.use";
private void Init()
{
permission.RegisterPermission(PermUse, this);
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
{
// Looks fine for a clean gunfight, but throws when info is null
// (decay, radiation, starvation) or when InitiatorPlayer is null
// (fall damage, fire spread, animal or turret kills).
BasePlayer killer = info.InitiatorPlayer;
if (!permission.UserHasPermission(killer.UserIDString, PermUse))
{
return;
}
string victim = entity.OwnerID.ToString();
killer.ChatMessage($"You killed {victim}, reward sent.");
}
}
}using System;
namespace Oxide.Plugins
{
[Info("KillRewards", "RustPluginGenerator", "1.0.0")]
[Description("Gives a small cash reward for player kills.")]
public class KillRewards : RustPlugin
{
private const string PermUse = "killrewards.use";
private void Init()
{
permission.RegisterPermission(PermUse, this);
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
{
if (entity == null || entity.IsDestroyed)
{
return;
}
// No attacker context: decay, starvation, radiation and similar.
if (info == null)
{
return;
}
// Death was not caused by a connected player: fall damage,
// fire spread, animals, turrets, or the server itself.
BasePlayer killer = info.InitiatorPlayer;
if (killer == null || !killer.IsConnected)
{
return;
}
if (!permission.UserHasPermission(killer.UserIDString, PermUse))
{
return;
}
string victimName = entity is BasePlayer ? ((BasePlayer)entity).displayName : entity.ShortPrefabName;
killer.ChatMessage($"You killed {victimName}, reward sent.");
}
}
}FAQ
Does OnEntityDeath fire on every entity death, or only players?
It fires for every BaseCombatEntity that dies: players, scientists, animals, and destructible combat entities. Your method receives the entity and the HitInfo, so filter with if (!(entity is BasePlayer)) return; if the plugin only means to reward player kills.
Why does the plugin keep working after the error?
Oxide catches the exception, prints the Failed to call hook ... line with the stack trace, and leaves the plugin loaded. The hook keeps firing on later deaths, so each new bad case produces another log line. That is why the console shows the same stack repeated.
Should I also guard the victim in OnEntityDeath?
Yes. entity can be a corpse-bound or half torn-down entity by the time another handler sees the death. Check entity == null || entity.IsDestroyed before reading OwnerID, health or transform, and store what you need before starting timers.
Do I need the same checks in Carbon?
Carbon loads the same plugin file and routes the same Oxide hooks with the same arguments, so the null cases are identical. Fix the source once; both frameworks pass an empty HitInfo when there is no attacker.
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