dotnet/wpf · error · ArgumentException

SR.Stylus_MatrixNotInvertable

Error message

SR.Stylus_MatrixNotInvertable

What it means

The RawStylusInput constructor requires a tabletToElementTransform that can be inverted, because stylus sample points must be mapped from tablet coordinates into element coordinates (and the transform is accessed from multiple threads, hence also required frozen). Passing a transform whose Inverse is null (a non-invertible matrix, e.g. zero-scale) throws ArgumentException with SR.Stylus_MatrixNotInvertable.

Solutions

  1. Check tabletToElementTransform.Inverse != null before constructing RawStylusInput and bail or substitute an identity transform.
  2. Avoid degenerate element layouts: ensure the target element has non-zero width/height (no collapsed dimensions) when computing the transform.
  3. Freeze the GeneralTransform before use, as the constructor also asserts IsFrozen for cross-thread access.
  4. If scale animation can reach 0, clamp it (e.g. Math.Max(0.001, scale)) before building the matrix.

Example fix

// before
var input = new RawStylusInput(report, tabletToElement, pluginCollection); // throws if not invertible

// after
if (tabletToElement.Inverse == null)
    tabletToElement = Transform.Identity;
if (!tabletToElement.IsFrozen)
    tabletToElement.Freeze();
var input = new RawStylusInput(report, tabletToElement, pluginCollection);
Defensive patterns

Strategy: validation

Validate before calling

if (tabletToElementTransform?.Inverse == null)
    tabletToElementTransform = Transform.Identity;
if (tabletToElementTransform.CanFreeze && !tabletToElementTransform.IsFrozen)
    tabletToElementTransform.Freeze();

Type guard

static bool IsUsableTabletTransform(GeneralTransform t) =>
    t != null && t.Inverse != null && t.IsFrozen;

Try / catch

try
{
    var input = new RawStylusInput(report, tabletToElement, pluginCollection);
}
catch (ArgumentException ex) when (ex.ParamName == nameof(tabletToElementTransform))
{
    // non-invertible transform: fall back to identity or skip this frame
}

Prevention

When it happens

Trigger: Constructing RawStylusInput with a GeneralTransform whose underlying Matrix is non-invertible — typically a scale of 0 on an axis, a collapsed layout (Width/Height = 0 producing a degenerate matrix), or a custom transform failing to produce an inverse.

Common situations: Stylus plug-in code computing the transform from an element with zero width/height or an AnimationClock holding scale at 0; a collapsed Visibility element inside a stylus plug-in pipeline; custom GeneralTransform implementations returning null Inverse.

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 dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/b6c3aa2f1f557382. Report an issue: GitHub.

Appendix: source

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

    /// </summary>
    public class RawStylusInput
    {
        /////////////////////////////////////////////////////////////////////
        /// <summary>
        ///     [TBS]
        /// </summary>
        /// <param name="report">[TBS]</param>
        /// <param name="tabletToElementTransform">[TBS]</param>
        /// <param name="targetPlugInCollection">[TBS]</param>
        internal RawStylusInput(
            RawStylusInputReport    report,
            GeneralTransform        tabletToElementTransform,
            StylusPlugInCollection targetPlugInCollection)
        {
            ArgumentNullException.ThrowIfNull(report);
            if (tabletToElementTransform.Inverse == null)
            {
                throw new ArgumentException(SR.Stylus_MatrixNotInvertable, nameof(tabletToElementTransform));
            }
            ArgumentNullException.ThrowIfNull(targetPlugInCollection);

            // We should always see this GeneralTransform is frozen since we access this from multiple threads.
            System.Diagnostics.Debug.Assert(tabletToElementTransform.IsFrozen);
            _report                 = report;
            _tabletToElementTransform  = tabletToElementTransform;
            _targetPlugInCollection = targetPlugInCollection;
        }

        /// <summary>
        /// 
        /// </summary>
        public int StylusDeviceId { get { return _report.StylusDeviceId; } }    

        /// <summary>
        /// 
        /// </summary>

View on GitHub (pinned to 81131a70a4)