AvaloniaUI/Avalonia · error · InvalidOperationException

Could not get platform handle

Error message

Could not get platform handle

What it means

In the macOS embedding test app, an Avalonia NativeControlHost root needs a real NSView handle. TryGetPlatformHandle returns null when the underlying AvaloniaView has not yet produced a platform surface. The InvalidOperationException means the embeddable view is not yet realized/attached, so there is no NSView to hand to the native window.

Source

Thrown at samples/IntegrationTestApp/Pages/EmbeddingPage.axaml.cs:85

        root.Prepare();

        var window = new NSWindow(
            new CGRect(0, 0, root.Width, root.Height),
            NSWindowStyle.Titled | NSWindowStyle.Closable,
            NSBackingStore.Buffered,
            false);

        window.Identifier = "ModalNativeWindow";
        window.WillClose += (_, _) => NSApplication.SharedApplication.StopModal();

        button.Click += (_, _) =>
        {
            ModalResultTextBox.Text = "Clicked";
            window.Close();
        };

        if (root.TryGetPlatformHandle() is not { } handle)
            throw new InvalidOperationException("Could not get platform handle");

        window.ContentView = (NSView)Runtime.GetNSObject(handle.Handle)!;
        root.StartRendering();

        return window;
    }
}

View on GitHub (pinned to 11c5427268)

Solutions

  1. Defer embedding until the view is attached and its TopLevel platform handle exists (e.g. in a Loaded/AttachedToVisualTree handler).
  2. Guard with `if (root.TryGetPlatformHandle() is { } handle)` and skip or retry rather than throwing during early init.
  3. Ensure an Avalonia macOS app lifecycle (UseMacOS()) is running so the platform surface is created.
  4. Verify the NativeControlHost root is actually part of a realized TopLevel before calling.

Example fix

// before
if (root.TryGetPlatformHandle() is not { } handle)
    throw new InvalidOperationException("Could not get platform handle");

// after (defer / guard instead of throwing)
if (root.TryGetPlatformHandle() is not { } handle)
{
    // not realized yet; retry on attach
    root.AttachedToVisualTree += (_, _) => AttachNativeWindow(root);
    return;
}
Defensive patterns

Strategy: type-guard

Validate before calling

// only embed when a real handle exists
if (root.TryGetPlatformHandle() is not { } handle) return;

Type guard

static bool HasPlatformHandle(INativeControlHostImplRoot r) => r.TryGetPlatformHandle() is not null;

Try / catch

try { /* build window.ContentView */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("platform handle"))
{ /* defer to AttachedToVisualTree */ }

Prevention

When it happens

Trigger: Calling TryGetPlatformHandle() on a NativeControlHost root that has not been attached/realized to a TopLevel (no platform backend created yet), typically during early init or before the view is added to the visual tree.

Common situations: Invoking the embedding code path before the Avalonia application/window is fully initialized; calling on a headless or detached view; macOS-specific path where the NSView is created lazily on first render.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/2794b846ee2c1efd. Report an issue: GitHub.