dotnet/wpf · error · ArgumentException

SR.StringEmpty (parameter name: name)

Error message

SR.StringEmpty (parameter name: name)

What it means

RoutedCommand's constructor requires a non-null, non-empty name string; an empty string throws ArgumentException with SR.StringEmpty. The name is part of the command's identity and is used for display and registration.

Solutions

  1. Pass a meaningful non-empty name, e.g. new RoutedCommand("Save", typeof(Window)).
  2. Validate the name source before constructing; fall back to a default name if the lookup returns empty.
  3. If the name is unknown, use the parameterless RoutedCommand() constructor which generates one.

Example fix

// before
var cmd = new RoutedCommand(resourceKey, typeof(MainWindow)); // resourceKey == ""
// after
var name = string.IsNullOrEmpty(resourceKey) ? "DefaultCommand" : resourceKey;
var cmd = new RoutedCommand(name, typeof(MainWindow));
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(name)) throw new ArgumentException("Command name must be non-empty", nameof(name));
var cmd = new RoutedCommand(name, ownerType);

Try / catch

try { var cmd = new RoutedCommand(name, typeof(Window)); } catch (ArgumentException ex) { /* use parameterless RoutedCommand() */ }

Prevention

When it happens

Trigger: new RoutedCommand("", ownerType) or new RoutedCommand(string.Empty, typeof(Window), gestures).

Common situations: Command names generated dynamically (e.g. from metadata or resource lookups) that resolve to empty strings when a resource key is missing.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/RoutedCommand.cs:50

        /// <param name="name">Declared Name of the RoutedCommand for Serialization</param>
        /// <param name="ownerType">Type that is registering the property</param>
        public RoutedCommand(string name, Type ownerType) : this(name, ownerType, null)
        {
        }

        /// <summary>
        /// RoutedCommand Constructor with Name and OwnerType
        /// </summary>
        /// <param name="name">Declared Name of the RoutedCommand for Serialization</param>
        /// <param name="ownerType">Type that is registering the property</param>
        /// <param name="inputGestures">Default Input Gestures associated</param>
        public RoutedCommand(string name, Type ownerType, InputGestureCollection inputGestures)
        {
            ArgumentNullException.ThrowIfNull(name);

            if (name.Length == 0)
            {
                throw new ArgumentException(SR.StringEmpty, nameof(name));
            }

            ArgumentNullException.ThrowIfNull(ownerType);

            _name = name;
            _ownerType = ownerType;
            _inputGestureCollection = inputGestures;
        }

        /// <summary>
        /// RoutedCommand Constructor with Name and OwnerType and command identifier.
        /// </summary>
        /// <param name="name">Declared Name of the RoutedCommand for Serialization</param>
        /// <param name="ownerType">Type that is registering the property</param>
        /// <param name="commandId">Byte identifier for the command assigned by the owning type</param>
        internal RoutedCommand(string name, Type ownerType, byte commandId) : this(name, ownerType, null)
        {
            _commandId = commandId;

View on GitHub (pinned to 81131a70a4)