dotnet/wpf · error · InvalidOperationException

VisualTarget_AnotherTargetAlreadyConnected

Error message

VisualTarget_AnotherTargetAlreadyConnected

What it means

HostVisual.BeginHosting throws InvalidOperationException with 'VisualTarget_AnotherTargetAlreadyConnected' when the HostVisual already has a composition target attached. A HostVisual can only host one VisualTarget for its lifetime; re-hosting is an invalid state transition.

Solutions

  1. Create a new HostVisual for each VisualTarget connection
  2. Detach/dispose the old VisualTarget and HostVisual before hosting a new target
  3. Track whether the HostVisual is already connected and reuse the existing VisualTarget

Example fix

// before
hostVisual.BeginHosting(new VisualTarget(hostVisual)); // second call
// after
if (hostVisual.Target == null)
{
    hostVisual.BeginHosting(new VisualTarget(hostVisual));
}
else
{
    hostVisual = new HostVisual();
    hostVisual.BeginHosting(new VisualTarget(hostVisual));
}
Defensive patterns

Strategy: validation

Validate before calling

if (hostVisual.Target != null)
    throw new InvalidOperationException("HostVisual already connected; create a new HostVisual.");

Type guard

bool CanHost(HostVisual hv) => hv != null && hv.Target == null;

Try / catch

try { hostVisual.BeginHosting(target); }
catch (InvalidOperationException) { hostVisual = new HostVisual(); hostVisual.BeginHosting(target); }

Prevention

When it happens

Trigger: Creating a second VisualTarget and calling BeginHosting with the same HostVisual instance that already has _target set (e.g. re-creating a VisualTarget on the same HostVisual after a render-thread reset).

Common situations: Multi-threaded UI scenarios that swap render targets dynamically (common in HwndSource/VisualTarget cross-thread rendering), where a new VisualTarget is created per frame or per device and reused with one HostVisual.

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


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/HostVisual.cs:145

        /// </summary>
        internal void BeginHosting(VisualTarget target)
        {
            //
            // This method is executed on the visual target thread.
            //

            Debug.Assert(target != null);
            Debug.Assert(target.Dispatcher.Thread == Thread.CurrentThread);

            using (CompositionEngineLock.Acquire())
            {
                //
                // Check if another target is already hosted by this
                // visual and throw exception if this is the case.
                //
                if (_target != null)
                {
                    throw new InvalidOperationException(
                        SR.VisualTarget_AnotherTargetAlreadyConnected
                        );
                }

                _target = target;

                //
                // If HostVisual and VisualTarget on same thread, then call Invalidate
                // directly. Otherwise post invalidate message to the host visual thread
                // indicating that content update is required.
                //
                if (this.CheckAccess())
                {
                    Invalidate();
                }
                else
                {
                    Dispatcher.BeginInvoke(

View on GitHub (pinned to 81131a70a4)