dotnet/wpf · error · ArgumentNullException

SR.Stylus_PlugInIsNull

Error message

SR.Stylus_PlugInIsNull

What it means

StylusPlugInCollection.InsertItem (invoked by collection Add/Insert) verifies dispatcher access and rejects a null plug-in with ArgumentNullException carrying SR.Stylus_PlugInIsNull. A StylusPlugInCollection can only contain real StylusPlugIn instances.

Solutions

  1. Check the plug-in instance for null before adding it to the collection
  2. Fix whatever produces the null plug-in (DI registration, type resolution, resource loading)
  3. Ensure the code runs on the element's dispatcher thread to avoid the VerifyAccess failure that can precede this check

Example fix

// before
inkCanvas.StylusPlugIns.Add(GetMyPlugIn()); // GetMyPlugIn may return null
// after
var plugin = GetMyPlugIn();
if (plugin != null)
{
    inkCanvas.StylusPlugIns.Add(plugin);
}
Defensive patterns

Strategy: validation

Validate before calling

if (plugin is null) throw new InvalidOperationException("StylusPlugIn not initialized");
inkCanvas.StylusPlugIns.Add(plugin);

Type guard

static bool IsValidPlugIn(StylusPlugIn p) => p is not null;

Try / catch

try { plugIns.Add(plugin); } catch (ArgumentNullException ex) when (ex.ParamName == "plugIn") { /* fix plug-in construction */ }

Prevention

When it happens

Trigger: Calling stylusPlugIns.Add(null) or stylusPlugIns.Insert(index, null) on a UIElement's StylusPlugIns collection from the UI thread.

Common situations: A factory/locator method that resolves a StylusPlugIn lazily returns null (DI misconfiguration, missing assembly/type), and the null is passed straight to Add.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Stylus/Common/StylusPlugInCollection.cs:38

    public sealed class StylusPlugInCollection : Collection<StylusPlugIn>
    {
        #region Protected APIs

        /// <summary>
        /// Insert a StylusPlugIn in the collection at a specific index. 
        /// This method should be called from the application context only
        /// </summary>
        /// <param name="index">index at which to insert the StylusPlugIn object</param>
        /// <param name="plugIn">StylusPlugIn object to insert, downcast to an object</param>
        protected override void InsertItem(int index, StylusPlugIn plugIn)
        {
            // Verify it's called from the app dispatcher
            _element.VerifyAccess();

            // Validate the input parameter
            if (null == plugIn)
            {
                throw new ArgumentNullException(nameof(plugIn), SR.Stylus_PlugInIsNull);
            }

            if (IndexOf(plugIn) != -1)
            {
                throw new ArgumentException(SR.Stylus_PlugInIsDuplicated, nameof(plugIn));
            }

            // Disable processing of the queue during blocking operations to prevent unrelated reentrancy
            // which a call to Lock() can cause.
            ExecuteWithPotentialDispatcherDisable(() =>
            {
                if (_stylusPlugInCollectionImpl.IsActiveForInput)
                {
                    // If we are currently active for input then we have a _penContexts that we must lock!
                    ExecuteWithPotentialLock(() =>
                     {
                         System.Diagnostics.Debug.Assert(this.Count > 0); // If active must have more than one plugin already
                         base.InsertItem(index, plugIn);

View on GitHub (pinned to 81131a70a4)