AvaloniaUI/Avalonia · critical · ArgumentException

Surface handle can't be 0x0

Error message

Surface handle can't be 0x0

What it means

Thrown by VulkanSupport.CreateAndroidSurface when the native surface handle passed in is IntPtr.Zero. VkCreateAndroidSurfaceKHR requires a valid ANativeWindow pointer; a zero handle means the window/surface was never created or was destroyed before the Vulkan surface could be built.

Source

Thrown at src/Android/Avalonia.Android/Platform/Vulkan/VulkanSupport.cs:58

            {
                _handle = handle;
            }

            public double Scaling => _handle.Scaling;
            public PixelSize Size => _handle.Size;
            public ulong CreateSurface(IVulkanPlatformGraphicsContext context) =>
                CreateAndroidSurface(_handle.Handle, context.Instance);

            public void Dispose()
            {
                // No-op
            }
        }

        private static ulong CreateAndroidSurface(nint handle, IVulkanInstance instance)
        {
            if(handle == IntPtr.Zero)
                throw new ArgumentException("Surface handle can't be 0x0", nameof(handle));
            var vulkanAndroid = new AndroidVulkanInterface(instance);
            var createInfo = new VkAndroidSurfaceCreateInfoKHR()
            {

                sType = VkAndroidSurfaceCreateInfoKHR.VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
                window = handle
            };
            VulkanException.ThrowOnError("vkCreateAndroidSurfaceKHR",
                vulkanAndroid.vkCreateAndroidSurfaceKHR(instance.Handle, ref createInfo, IntPtr.Zero, out var surface));
            return surface;
        }
    }
}

View on GitHub (pinned to 11c5427268)

Solutions

  1. Ensure the surface is created (SurfaceWindowCreated fired with a valid handle) before the Vulkan graphics context is initialized.
  2. Defer Vulkan surface creation until InvalidationAwareSurfaceView exposes a non-zero native window handle.
  3. On surface destroy, tear down the Vulkan swapchain/surface before the handle goes to zero.
  4. If Vulkan reliability is a concern, fall back to the Skia/Framebuffer backend via .With(new SkiaOptions()).

Example fix

// before
// vulkan context created eagerly in constructor, surface may be 0x0
 graphicsContext = vulkanPlatform.CreateContext();

// after — wait for a valid surface handle
_surfaceView.SurfaceWindowCreated += (s, e) =>
{
    if (((IPlatformHandle)_surfaceView).Handle != IntPtr.Zero)
        graphicsContext = vulkanPlatform.CreateContext();
};
Defensive patterns

Strategy: validation

Validate before calling

// confirm the surface handle is valid before creating the Vulkan surface
if (((IPlatformHandle)surfaceView).Handle == IntPtr.Zero)
    return; // surface not ready
var surface = vulkanPlatform.CreateSurface(context);

Type guard

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

Prevention

When it happens

Trigger: Calling CreateSurface(IVulkanPlatformGraphicsContext) when the context's surface handle (typically the InvalidationAwareSurfaceView's native window handle) is zero. Same root cause as the ANativeWindow framebuffer error: surface not yet created, already destroyed, or view detached.

Common situations: Selecting the Vulkan render backend while the surface is not ready; lifecycle race during pause/resume; embedding AvaloniaView detached from the window; using Vulkan on a device/config where the surface creation timing differs; combining Vulkan with a custom surface view that yields a zero handle.

Related errors


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