PrismLibrary/Prism · error · InvalidOperationException

Resources.CannotRegisterSameCommandTwice

Error message

Resources.CannotRegisterSameCommandTwice

What it means

CompositeCommand.RegisterCommand throws InvalidOperationException (Resources.CannotRegisterSameCommandTwice) if the exact command instance is already in _registeredCommands. Each child must be registered only once so Execute/CanExecute voting is not duplicated.

Solutions

  1. Guard registration with a check (e.g. composite.RegisteredCommands.Contains(cmd)).
  2. Unregister the command before re-registering if re-initialization is intended.
  3. Move registration to a place guaranteed to run once (constructor, not OnAppearing).

Example fix

// before
protected override void OnAppearing()
{
    _composite.RegisterCommand(SaveCommand); // runs every appearance
}
// after
protected override void OnAppearing()
{
    if (!_composite.RegisteredCommands.Contains(SaveCommand))
        _composite.RegisterCommand(SaveCommand);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!composite.RegisteredCommands.Contains(SaveCommand))
    composite.RegisterCommand(SaveCommand);

Try / catch

try { composite.RegisterCommand(cmd); }
catch (InvalidOperationException ex) when (ex.Message.Contains("twice")) { /* already registered — safe to ignore */ }

Prevention

When it happens

Trigger: Calling RegisterCommand twice with the same ICommand instance — e.g. re-running initialization code, re-subscribing on page revisit, or double construction of a ViewModel.

Common situations: View appearing multiple times triggering setup code that registers commands again; event handlers wired more than once; hot-reload re-executing registration.

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


AI-assisted analysis of PrismLibrary/Prism@358118cd64 (2026-09-15). Data as JSON: /api/errors/8072403873c02d31. Report an issue: GitHub.

Appendix: source

Thrown at src/Prism.Core/Commands/CompositeCommand.cs:61

        ///  <remarks>
        /// If this command is set to monitor command activity, and <paramref name="command"/> 
        /// implements the <see cref="IActiveAware"/> interface, this method will subscribe to its
        /// <see cref="IActiveAware.IsActiveChanged"/> event.
        /// </remarks>
        /// <param name="command">The command to register.</param>
        public virtual void RegisterCommand(ICommand command)
        {
            if (command == null) throw new ArgumentNullException(nameof(command));
            if (command == this)
            {
                throw new ArgumentException(Resources.CannotRegisterCompositeCommandInItself);
            }

            lock (_registeredCommands)
            {
                if (_registeredCommands.Contains(command))
                {
                    throw new InvalidOperationException(Resources.CannotRegisterSameCommandTwice);
                }
                _registeredCommands.Add(command);
            }

            command.CanExecuteChanged += _onRegisteredCommandCanExecuteChangedHandler;
            OnCanExecuteChanged();

            if (_monitorCommandActivity)
            {
                if (command is IActiveAware activeAwareCommand)
                {
                    activeAwareCommand.IsActiveChanged += Command_IsActiveChanged;
                }
            }
        }

        /// <summary>
        /// Removes a command from the collection and removes itself from the <see cref="ICommand.CanExecuteChanged"/> event of it.

View on GitHub (pinned to 358118cd64)