devlooped/moq · error · ArgumentException
Resources.SetupNotEventRemove (formatted with…
Error message
Resources.SetupNotEventRemove (formatted with part.Expression)
What it means
Symmetric to the add-accessor case: when Raise resolves an event remove accessor (e => e.MyEvent -= null) but no event on the mock's concrete type exposes that method as its remove method, Moq throws ArgumentException with Resources.SetupNotEventRemove, because it cannot map the accessor back to its EventInfo.
Solutions
- Use mock.As<IInterface>().Raise(e => e.Event -= null, args) targeting the declaring interface
- Declare events once on a mockable (non-sealed) base and avoid hiding with 'new'
- Check that the event's declaring type is accessible to Moq's reflection (public or internals visible to DynamicProxyGenAssembly2)
- Invoke the event through production code or an OnEvent helper rather than Raise for exotic event layouts
Example fix
// before mock.Raise(x => x.HiddenEvent -= null, EventArgs.Empty); // accessor not resolvable -> throws // after mock.As<IEventSource>().Raise(e => e.SourceEvent -= null, EventArgs.Empty);
Defensive patterns
Strategy: try-catch
Validate before calling
var evt = mock.Object.GetType().GetEvents()
.FirstOrDefault(e => e.GetRemoveMethod(true) != null && e.Name == nameof(IEventSource.SourceEvent));
// null means Raise(e => e.SourceEvent -= null, ...) will throw Try / catch
try
{
mock.Raise(x => x.SourceEvent -= null, EventArgs.Empty);
}
catch (ArgumentException ex) when (ex.Message.Contains("SetupNotEventRemove"))
{
mock.As<IEventSource>().Raise(e => e.SourceEvent -= null, EventArgs.Empty);
} Prevention
- Target the event's declaring interface with mock.As<T>().Raise rather than the concrete class
- Keep event add/remove accessors compiler-generated (no custom event accessors that break reflection)
- Avoid redeclaring events in derived mock types
When it happens
Trigger: mock.Raise(x => x.SomeEvent -= null, ...) where the remove accessor comes from an explicitly implemented interface event, a hidden/new event, or a type whose events are not visible under the binding flags used, leaving GetEvents(...).SingleOrDefault(e => e.GetRemoveMethod(true) == implementingMethod) empty.
Common situations: Explicit interface event implementations on mocked classes; duplicated event declarations across inheritance hierarchies; reflection over mock.Object.GetType() returning a subclass that hides the event.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Resources.SetupNotEventAdd (formatted with part.Expression)
- Resources.UnsupportedExpression (formatted with expression)
- Unsupported expression
- Could not determine the correct positions for all argument…
- The return type of the last member shown above is not…
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/a69b45e089567fbf.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/Mock.cs:736
if (parts.Count == 0)
{
EventInfo @event;
if (method.IsEventAddAccessor())
{
var implementingMethod = method.GetImplementingMethod(mock.Object.GetType());
@event = implementingMethod.DeclaringType!.GetEvents(bindingFlags)
.SingleOrDefault(e => e.GetAddMethod(true) == implementingMethod)
?? throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.SetupNotEventAdd,
part.Expression));
}
else if (method.IsEventRemoveAccessor())
{
var implementingMethod = method.GetImplementingMethod(mock.Object.GetType());
@event = implementingMethod.DeclaringType!.GetEvents(bindingFlags)
.SingleOrDefault(e => e.GetRemoveMethod(true) == implementingMethod)
?? throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.SetupNotEventRemove,
part.Expression));
}
else
{
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
Resources.UnsupportedExpression,
expression));
}
if (mock.EventHandlers.TryGet(@event, out var handlers))
{
var returnType = handlers.GetMethodInfo().ReturnType;
if (returnType == typeof(Task) || returnType.FullName == "System.Threading.Tasks.ValueTask")
{View on GitHub (pinned to 89a5be629c)