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

  1. Verify the handler delegate is assigned before calling Check; add a null check on the caller side.
  2. If the handler comes from a registry/dictionary lookup, confirm the lookup key exists and fall back or log before calling Check.
  3. Fix the initialization order so the handler field/method group is created before any Check/Subscribe/Unsubscribe calls.
  4. 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

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


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)