dotnet/wpf · error · InvalidOperationException
SR.CannotProcessInkCommand
Error message
SR.CannotProcessInkCommand
What it means
StickyNoteControl throws InvalidOperationException when the InkCommand (a RoutedCommand that sets the ink editing mode) is executed on a sticky note whose content is null or is not an Ink sticky note (StickyNoteType.Text). The command only makes sense on notes that hold InkCanvas content. The library guards so the InkCanvasEditingMode is never applied to a non-ink note.
Solutions
- Ensure the StickyNoteControl's Content is an InkCanvas (or set its Type to Ink) before invoking InkCommand.
- Gate the command with a CanExecute that checks content != null && content.Type == StickyNoteType.Ink.
- Use different commands (text editing commands) for text-type sticky notes.
Example fix
// before
snc.SetValue(StickyNoteControl.InkEditingModeProperty, InkCanvasEditingMode.Ink);
// after
if (snc.Content is StickyNoteContentControl c && c.Type == StickyNoteType.Ink)
{
snc.SetValue(StickyNoteControl.InkEditingModeProperty, InkCanvasEditingMode.Ink);
} Defensive patterns
Strategy: validation
Validate before calling
bool canInk = snc.Content != null && snc.Content.Type == StickyNoteType.Ink; if (canInk) StickyNoteControl.InkCommand.Execute(mode, snc);
Type guard
static bool IsInkNote(StickyNoteControl s) => s?.Content is StickyNoteContentControl c && c.Type == StickyNoteType.Ink;
Try / catch
try { StickyNoteControl.InkCommand.Execute(mode, snc); }
catch (InvalidOperationException ex) { Log.Warn("InkCommand ignored: note is not ink-capable", ex); } Prevention
- Check Content.Type before enabling ink UI
- Bind command availability (CanExecute) to note type
- Do not share one command across text and ink notes
When it happens
Trigger: Executing StickyNoteControl.InkCommand (e.g. via a CommandBinding, toolbar button, or InputBinding) while the targeted StickyNoteControl has no content (Content == null) or its Content.Type is StickyNoteType.Text instead of StickyNoteType.Ink.
Common situations: XAML toolbars that wire InkCommand globally so it fires for every sticky note including text notes; notes created without content yet; notes whose content was programmatically switched to text while the command was still bound.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Animation_Invalid_DefaultValue
- ArgumentOutOfRangeException(nameof(oldProperty))
- ArgumentOutOfRangeException(nameof(percentageWithinBounds))
- ArgumentOutOfRangeException(nameof(percentageWithinLasso))
- ArgumentOutOfRangeException(percentageWithinBounds)
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/0189be31f684fc56.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/StickyNote.cs:1679
RoutedCommand command = (RoutedCommand)(args.Command);
StickyNoteControl snc = sender as StickyNoteControl;
Invariant.Assert(snc != null, "Unexpected Commands");
Invariant.Assert(command == StickyNoteControl.DeleteNoteCommand
|| command == StickyNoteControl.InkCommand, "Unknown Commands");
if ( command == StickyNoteControl.DeleteNoteCommand )
{
// DeleteNote Command
snc.DeleteStickyNote();
}
else if (command == StickyNoteControl.InkCommand)
{
StickyNoteContentControl content = snc.Content;
if (content == null || content.Type != StickyNoteType.Ink)
{
throw new InvalidOperationException(SR.CannotProcessInkCommand);
}
// Set the StickyNoteControl's ink editing mode to the command's parameter
InkCanvasEditingMode mode = (InkCanvasEditingMode)args.Parameter;
snc.SetValue(InkEditingModeProperty, mode);
}
}
/// <summary>
/// QueryCommandEnabled Handler - determines if a command should be enabled or not.
/// DeleteNoteCommand - if the SNC has an attached annotation
/// InkCommand - if the SNC is of type InkStickyNote
/// AllOthers - if focus is on our inner control, we let the inner control decide,
/// otherwise we return false
/// </summary>
private static void _OnQueryCommandEnabled(object sender, CanExecuteRoutedEventArgs args)
{
RoutedCommand command = (RoutedCommand)( args.Command );View on GitHub (pinned to 81131a70a4)