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
- Check tabletToElementTransform.Inverse != null before constructing RawStylusInput and bail or substitute an identity transform.
- Avoid degenerate element layouts: ensure the target element has non-zero width/height (no collapsed dimensions) when computing the transform.
- Freeze the GeneralTransform before use, as the constructor also asserts IsFrozen for cross-thread access.
- 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
- Always check Inverse != null before constructing RawStylusInput.
- Avoid degenerate layouts: don't attach plug-ins to elements with zero width/height.
- Freeze transforms before passing them in (the constructor asserts IsFrozen).
- Clamp scale animations so they never reach exactly 0.
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
- captureMode
- SR.InvalidStylusPointConstructionZeroLengthCollection
- SR.InvalidStylusPointPropertyInfoResolution
- SR.Stylus_InvalidMax
- ' ' is not a valid value for ' '.
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)