EllanJiang/GameFramework · error · GameFrameworkException
Event handler is invalid.
Error message
Event handler is invalid.
What it means
EventPool.Check validates that the supplied EventHandler<T> delegate is not null before querying whether the event pool already contains a handler for the given event id. If handler is null, the library cannot perform a meaningful containment check, so it throws GameFrameworkException('Event handler is invalid.'). This is a fail-fast guard protecting the internal m_EventHandlers collection from null delegates.
Solutions
- Verify the handler delegate is assigned before calling Check; add a null check on the caller side.
- If the handler comes from a registry/dictionary lookup, confirm the lookup key exists and fall back or log before calling Check.
- Fix the initialization order so the handler field/method group is created before any Check/Subscribe/Unsubscribe calls.
- Wrap subscription logic in a guard: if (handler == null) return/log instead of delegating to Check.
Example fix
// before
if (m_EventPool.Check((int)GameEvent.MyEvent, MyHandler)) { ... }
// after
if (MyHandler != null && m_EventPool.Check((int)GameEvent.MyEvent, MyHandler)) { ... } Defensive patterns
Strategy: validation
Validate before calling
if (handler == null) throw new ArgumentNullException(nameof(handler)); bool exists = eventPool.Check(id, handler);
Type guard
bool IsValidHandler<TArgs>(EventHandler<TArgs> handler) where TArgs : GameFrameworkEventArgs => handler is not null;
Try / catch
try
{
bool exists = eventPool.Check(id, handler);
}
catch (GameFrameworkException ex) when (ex.Message == "Event handler is invalid.")
{
// handler was null — log and skip
} Prevention
- Never pass unassigned delegate fields to Check/Subscribe/Unsubscribe.
- Resolve handlers from registries only after verifying the lookup succeeded.
- Initialize handler delegates in Awake/constructor before any event pool usage.
- Centralize subscription helper methods that null-check once for the whole codebase.
When it happens
Trigger: Calling eventPool.Check(id, null) — most often when the handler was stored in a field/variable that was never assigned, or a method returns a delegate that is null (e.g. a target object method that no longer exists so the delegate creation yielded null after refactors or conditional initialization).
Common situations: Passing a class member method group whose instance is conditionally constructed; refactoring renamed a handler method and a null-conditional delegate path silently returns null; passing the result of a lookup (dictionary/registry of handlers) that missed; C# EventHandler<T> field left at default before subscription setup code runs.
Related errors
- Ensure size is invalid.
- Event ' ' not allow multi handler.
- Event ' ' not allow duplicate handler.
- Event ' ' not exists specified handler.
- Event is invalid.
AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15).
Data as JSON: /api/errors/f220fad350cb96da.
Report an issue: GitHub.
Appendix: source
Thrown at GameFramework/Base/EventPool/EventPool.cs:129
if (m_EventHandlers.TryGetValue(id, out range))
{
return range.Count;
}
return 0;
}
/// <summary>
/// 检查是否存在事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要检查的事件处理函数。</param>
/// <returns>是否存在事件处理函数。</returns>
public bool Check(int id, EventHandler<T> handler)
{
if (handler == null)
{
throw new GameFrameworkException("Event handler is invalid.");
}
return m_EventHandlers.Contains(id, handler);
}
/// <summary>
/// 订阅事件处理函数。
/// </summary>
/// <param name="id">事件类型编号。</param>
/// <param name="handler">要订阅的事件处理函数。</param>
public void Subscribe(int id, EventHandler<T> handler)
{
if (handler == null)
{
throw new GameFrameworkException("Event handler is invalid.");
}
if (!m_EventHandlers.Contains(id))View on GitHub (pinned to d0c010b051)