stride3d/stride · error · InvalidOperationException
The given is already registered as a clipboard listener.
Error message
The given {window} is already registered as a clipboard listener. What it means
ClipboardMonitor.RegisterListener throws InvalidOperationException when the given Window is already present in the static Listeners dictionary, because a window can only hook the clipboard chain once per monitor instance.
Solutions
- Call the unregister/deregister method for the window before calling RegisterListener again.
- Track registration state per window (e.g. a bool or Listeners.ContainsKey check) and skip duplicate registrations.
- Register once in the window's SourceInitialized/Loaded handler with a guard flag.
- Ensure cleanup runs on Closed so the same window can be safely re-registered later.
Example fix
// before
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
ClipboardMonitor.RegisterListener(this);
ClipboardMonitor.RegisterListener(this); // throws on 2nd call
}
// after
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
if (!_registered)
{
ClipboardMonitor.RegisterListener(this);
_registered = true;
}
} Defensive patterns
Strategy: try-catch
Validate before calling
if (!ClipboardMonitorIsRegistered(this))
ClipboardMonitor.RegisterListener(this); Type guard
static bool IsRegistered(Window w) => !ClipboardMonitorRegisteredWindows.Contains(w); // track locally
Try / catch
try { ClipboardMonitor.RegisterListener(this); }
catch (InvalidOperationException ex) when (ex.Message.Contains("already registered")) { /* already listening */ } Prevention
- Register exactly once, guarded by a flag, in SourceInitialized/Loaded
- Always unregister in Closed so re-registration is safe
- Avoid registering in both constructor and Loaded handlers
When it happens
Trigger: Calling ClipboardMonitor.RegisterListener(window) twice for the same Window instance without unregistering in between; re-registering after a window was shown/hidden but not unregistered.
Common situations: Registering in both a Loaded handler and a constructor; re-registering after theme/appearance change re-triggers initialization; forgetting to call the unregister counterpart on window close before reopening.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- This BehaviorCollection has already been attached to a…
- The given is not registered as a clipboard listener.
- The upgrader overlaps with another upgrader.
- Service is already registered with this type
- entity must contain a non-null asset entity.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/58f538cd4bf5b588.
Report an issue: GitHub.
Appendix: source
Thrown at sources/presentation/Stride.Core.Presentation.Wpf/Interop/ClipboardMonitor.cs:38
/// <summary>
/// Raised when the clipboard has changed and contains text.
/// </summary>
/// <remarks>The sender of this event a window that was previously registered as a clipboard viewer with <see cref="RegisterListener"/>.</remarks>
public static event EventHandler<EventArgs> ClipboardTextChanged;
/// <summary>
/// Registers the given <paramref name="window"/> as a clipboard viewer.
/// </summary>
/// <param name="window"></param>
/// <exception cref="ArgumentNullException">window is <c>null</c></exception>
/// <exception cref="InvalidOperationException">window is already registered.</exception>
public static void RegisterListener([NotNull] Window window)
{
if (window == null) throw new ArgumentNullException(nameof(window));
HwndSource hwndSource;
if (Listeners.TryGetValue(window, out hwndSource))
throw new InvalidOperationException($"The given {window} is already registered as a clipboard listener.");
hwndSource = GetHwndSource(window);
if (hwndSource == null)
return;
Listeners.Add(window, hwndSource);
window.Dispatcher.Invoke(() =>
{
// start processing window messages
hwndSource.AddHook(WinProc);
// set the window as a viewer
hwndNextViewer = NativeHelper.SetClipboardViewer(hwndSource.Handle);
});
}
/// <summary>
/// Unregisters the given <paramref name="window"/> as a clipboard viewer.View on GitHub (pinned to 96fad776d2)