AvaloniaUI/Avalonia · critical · Exception

Unable to obtain ANativeWindow

Error message

Unable to obtain ANativeWindow

What it means

Thrown by the AndroidFramebuffer constructor when the underlying InvalidationAwareSurfaceView exposes a zero (IntPtr.Zero) native window handle. The framebuffer needs a valid ANativeWindow pointer to lock and render pixels; a null handle means the Android Surface has not been created yet (or was already destroyed) at the time Avalonia tried to draw.

Source

Thrown at src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs:18

using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Avalonia.Platform;

namespace Avalonia.Android.Platform.SkiaPlatform
{
    unsafe class AndroidFramebuffer : ILockedFramebuffer
    {
        private IntPtr _window;

        public AndroidFramebuffer(InvalidationAwareSurfaceView surface, double scaling)
        {
            if(surface == null)
                throw new ArgumentNullException(nameof(surface));
            _window = (surface as IPlatformHandle).Handle;
            if (_window == IntPtr.Zero)
                throw new Exception("Unable to obtain ANativeWindow");
            ANativeWindow_Buffer buffer;
            var rc = new ARect()
            {
                right = ANativeWindow_getWidth(_window),
                bottom = ANativeWindow_getHeight(_window)
            };
            Size = new PixelSize(rc.right, rc.bottom);
            ANativeWindow_lock(_window, &buffer, &rc);

            (Format, AlphaFormat, RowBytes) = buffer.format == AndroidPixelFormat.WINDOW_FORMAT_RGB_565 ?
                (PixelFormat.Rgb565, AlphaFormat.Opaque, buffer.stride * 2) :
                (PixelFormat.Rgba8888, AlphaFormat.Premul, buffer.stride * 4);

            Address = buffer.bits;

            Dpi = new Vector(96, 96) * scaling;
        }

View on GitHub (pinned to 11c5427268)

Solutions

  1. Ensure rendering is gated on the SurfaceWindowCreated event and suppressed on SurfaceWindowDestroyed — let InvalidationAwareSurfaceView drive the render loop, do not call render externally before surface creation.
  2. If embedding AvaloniaView, make sure it is attached to a visible window (added to the view hierarchy and laid out) before any draw is requested.
  3. Avoid forcing framebuffer locks during Activity.onPause/onResume transitions; defer rendering until the host signals the surface is valid.
  4. Upgrade Avalonia.Android — newer versions may short-circuit rendering when InternalView or its handle is invalid instead of throwing.

Example fix

// before
_topLevelImpl.Surfaces.OfType<IFramebufferPlatformSurface>().First().CreateFramebufferRenderTarget();

// after — only render when the surface is actually ready
if (_surfaceView.IsSurfaceValid)
{
    _topLevelImpl.Surfaces.OfType<IFramebufferPlatformSurface>().First().CreateFramebufferRenderTarget();
}
Defensive patterns

Strategy: validation

Validate before calling

// before locking the framebuffer, confirm the surface has a valid window handle
var handle = (surfaceView as IPlatformHandle)?.Handle ?? IntPtr.Zero;
if (handle == IntPtr.Zero) return; // surface not ready — skip this frame

Type guard

static bool HasValidNativeWindow(InvalidationAwareSurfaceView? view)
    => view is IPlatformHandle h && h.Handle != IntPtr.Zero;

Try / catch

// framebuffer lock is internal; the actionable guard is to suppress rendering
// when the surface isn't ready rather than catching after the fact.
if (!HasValidNativeWindow(internalView)) return;

Prevention

When it happens

Trigger: Constructing AndroidFramebuffer via FramebufferManager.Lock() when (surface as IPlatformHandle).Handle returns IntPtr.Zero. This happens if rendering is requested before SurfaceCreated fired, after SurfaceDestroyed fired, or if the SurfaceView was never properly attached to the window hierarchy.

Common situations: Activity paused/resumed lifecycle races where a draw is scheduled between SurfaceDestroyed and SurfaceCreated; embedding AvaloniaView in a ViewPager/RecyclerView where the view is detached; calling TopLevel.RequestAnimationFrame or forcing a render before the surface is ready; custom embedding that bypasses InvalidationAwareSurfaceView's lifecycle hooks.

Related errors


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