stride3d/stride · error · ArgumentException

The given event info must have exactly two parameters.

Error message

The given event info must have exactly two parameters.

What it means

AnonymousEventHandler.RegisterEventHandler dynamically subscribes a handler to an arbitrary event via reflection. It expects the classic .NET event pattern of exactly two parameters (sender, args); if the EventInfo's handler delegate has any other parameter count, it throws ArgumentException because it cannot construct the generic AnonymousEventHandler<TArgs>.

Solutions

  1. Ensure the event uses a standard two-parameter delegate (EventHandler, EventHandler<TEventArgs>, or equivalent (object, TArgs) signature).
  2. Subscribe manually with a matching custom delegate instead of using RegisterEventHandler.
  3. Change the event's delegate type on the declaring type to follow the standard .NET event pattern.
  4. Validate parameterInfos.Length == 2 before calling and fall back to a manual subscription.

Example fix

// before (non-standard delegate)
public event Action<int> Progress; // 1 parameter
// after
public event EventHandler<int> Progress; // (object sender, int e)
Defensive patterns

Strategy: validation

Validate before calling

var invoke = eventInfo.EventHandlerType.GetMethod("Invoke");
if (invoke.GetParameters().Length != 2)
    throw new NotSupportedException($"Event {eventInfo.Name} does not follow the (sender, args) pattern");
AnonymousEventHandler.RegisterEventHandler(eventInfo, target, handler);

Type guard

bool IsStandardEventPattern(EventInfo e) =>
    e.EventHandlerType.GetMethod("Invoke").GetParameters().Length == 2;

Try / catch

try { AnonymousEventHandler.RegisterEventHandler(eventInfo, target, handler); }
catch (ArgumentException ex) when (ex.Message.Contains("exactly two parameters")) { /* subscribe manually with a delegate matching the custom signature */ }

Prevention

When it happens

Trigger: Calling RegisterEventHandler with an EventInfo whose EventHandlerType's Invoke method has a parameter count other than 2 — e.g. custom delegates like delegate void Callback(int code) or parameterless/hand-rolled delegate events.

Common situations: Reflective wiring of events on third-party or COM/interop objects that use non-standard delegates; hooking custom events that deviate from EventHandler<T> convention.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/78b62f99fc621449. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Core/AnonymousEventHandler.cs:23

using System.Reflection;
using Stride.Core.Annotations;

namespace Stride.Core.Presentation.Core
{
    public class AnonymousEventHandler
    {
        protected Action Action;
        private Delegate eventHandler;
        private EventInfo eventInfo;
        private object target;

        [NotNull]
        public static AnonymousEventHandler RegisterEventHandler([NotNull] EventInfo eventInfo, object target, Action handler)
        {
            var parameterInfos = eventInfo.EventHandlerType.GetMethod("Invoke").GetParameters();

            if (parameterInfos.Length != 2)
                throw new ArgumentException("The given event info must have exactly two parameters.");

            var argumentType = parameterInfos.Skip(1).First().ParameterType;
            var type = typeof(AnonymousEventHandler<>).MakeGenericType(argumentType);

            var method = type.GetMethod("Handler");
            var anonymousHandler = (AnonymousEventHandler)Activator.CreateInstance(type);
            anonymousHandler.Action = handler;
            anonymousHandler.eventHandler = Delegate.CreateDelegate(eventInfo.EventHandlerType, anonymousHandler, method);
            anonymousHandler.eventInfo = eventInfo;
            anonymousHandler.target = target;
            eventInfo.AddEventHandler(target, anonymousHandler.eventHandler);

            return anonymousHandler;
        }

        public static void UnregisterEventHandler([NotNull] AnonymousEventHandler handler)
        {
            handler.eventInfo.RemoveEventHandler(handler.target, handler.eventHandler);

View on GitHub (pinned to 96fad776d2)