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
- Defer embedding until the view is attached and its TopLevel platform handle exists (e.g. in a Loaded/AttachedToVisualTree handler).
- Guard with `if (root.TryGetPlatformHandle() is { } handle)` and skip or retry rather than throwing during early init.
- Ensure an Avalonia macOS app lifecycle (UseMacOS()) is running so the platform surface is created.
- 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
- Defer embedding until the view is attached/realized.
- Subscribe to AttachedToVisualTree and retry.
- Guard on TryGetPlatformHandle() instead of throwing during early init.
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
- Unable to export IOSurfaceRef
- IOSurfaceLock failed
- Need skia to dump textures, sorry
- Unable to export IOSurfaceRef
- The control isn't currently attached to a toplevel
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/2794b846ee2c1efd.
Report an issue: GitHub.