dotnet/wpf · error · ArgumentException

SR.SourceNotSet

Error message

SR.SourceNotSet

What it means

UIElement.RaiseEvent (and related routing entry points) requires the RoutedEventArgs to carry a Source. When args.Source is null the event cannot be routed sensibly, so an ArgumentException with SR.SourceNotSet is thrown. The library refuses to raise an event whose origin is unknown.

Solutions

  1. Set args.Source (e.g. args.Source = this;) before calling RaiseEvent
  2. Use UIElement.RaiseEvent with args whose RoutedEvent and Source are populated
  3. In test/synthesis code, construct RoutedEventArgs via a constructor overload that sets source

Example fix

// before
var args = new RoutedEventArgs(MyEvent);
element.RaiseEvent(args); // throws
// after
var args = new RoutedEventArgs(MyEvent) { Source = element };
element.RaiseEvent(args);
Defensive patterns

Strategy: validation

Validate before calling

if (args == null) throw new ArgumentNullException(nameof(args));
if (args.Source == null) args.Source = this; // or refuse to raise
element.RaiseEvent(args);

Type guard

static bool CanRaise(RoutedEventArgs args) => args?.Source != null && args.RoutedEvent != null;

Try / catch

try { element.RaiseEvent(args); }
catch (ArgumentException ex) when (ex.Message.Contains("Source")) { args.Source = element; element.RaiseEvent(args); }

Prevention

When it happens

Trigger: Calling RaiseEvent / RaiseImpl with a hand-constructed RoutedEventArgs (e.g. new RoutedEventArgs(SomeEvent)) without setting Source before raising.

Common situations: Custom control authors raising routed events from non-UI helper classes; replaying or synthesizing events from unit tests or message-processing code; deserializing event args.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/efd8211a0ce787f6. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/UIElement.cs:1644

        /// This method does nothing if layout is clean but it does work if layout is not clean so avoid calling
        /// it after each change in the element tree. It makes sense to either never call it (system will do this
        /// in a deferred manner) or only call it if you absolutely need updated sizes and positions after you do all changes.
        /// </remarks>
        public void UpdateLayout()
        {
//             VerifyAccess();
            ContextLayoutManager.From(Dispatcher).UpdateLayout();
        }

        internal static void BuildRouteHelper(DependencyObject e, EventRoute route, RoutedEventArgs args)
        {
            ArgumentNullException.ThrowIfNull(route);

            ArgumentNullException.ThrowIfNull(args);

            if (args.Source == null)
            {
                throw new ArgumentException(SR.SourceNotSet);
            }

            if (args.RoutedEvent != route.RoutedEvent)
            {
                throw new ArgumentException(SR.Mismatched_RoutedEvent);
            }

            // Route via visual tree
            if (args.RoutedEvent.RoutingStrategy == RoutingStrategy.Direct)
            {
                UIElement uiElement = e as UIElement;
                ContentElement contentElement = null;
                UIElement3D uiElement3D = null;

                if (uiElement == null)
                {
                    contentElement = e as ContentElement;

View on GitHub (pinned to 81131a70a4)