stride3d/stride · error · InvalidOperationException
Cannot create a swapchain: Vulkan surface extensions are…
Error message
Cannot create a swapchain: Vulkan surface extensions are not available. This may happen when using a headless ICD.
What it means
Before creating a VkSurfaceKHR, CreateSurface checks that the Vulkan instance was created with the required surface extensions (VK_KHR_surface plus platform ones) via GraphicsAdapterFactory.GetInstance(...).HasSurfaceSupport. If the instance lacks surface support — typical of headless ICDs or compute-only environments — it throws InvalidOperationException because no swapchain can be presented.
Solutions
- Install full graphics drivers and a display server (X11/Wayland) so the Vulkan loader exposes surface extensions.
- On WSL2, enable WSLg or run the app natively on Windows with D3D backend.
- Use the D3D11/D3D12 backend on Windows instead of Vulkan when only compute/headless Vulkan is available.
- For CI/offscreen rendering, avoid swapchain creation and render to offscreen textures instead.
Example fix
// before (container without display) dotnet StrideApp.dll // after: enable GPU + surface support docker run --gpus all -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix ...
Defensive patterns
Strategy: validation
Validate before calling
if (!GraphicsAdapterFactory.GetInstance(debug).HasSurfaceSupport)
throw new InvalidOperationException("Vulkan instance lacks surface extensions; cannot present"); Type guard
bool CanPresent(GraphicsAdapterFactory f) => f.GetInstance(isDebug: false).HasSurfaceSupport;
Try / catch
try { presenter = new SwapChainGraphicsPresenter(device, desc); }
catch (InvalidOperationException ex) when (ex.Message.Contains("headless ICD")) { log.Warn("No Vulkan surface support; falling back to D3D11 or offscreen rendering"); SwitchToAlternativeBackend(); } Prevention
- Verify DISPLAY/WAYLAND_DISPLAY are set before launching on Linux
- In containers/CI, use GPU passthrough with full driver stacks or avoid swapchains
- On WSL2 enable WSLg or use the D3D backend
- Check instance surface extension availability during app startup and pick backend accordingly
When it happens
Trigger: SwapChainGraphicsPresenter creation/recreation on a Vulkan instance without VK_KHR_*_surface extensions enabled, i.e. when HasSurfaceSupport is false (headless ICD, no display server, WSL without GPU surface support).
Common situations: Running in CI/containers with software Vulkan (lavapipe/headless ICD); SSH sessions without DISPLAY/WAYLAND_DISPLAY; WSL2 without WSLg; installing only compute drivers (e.g. NVIDIA compute-only driver) on servers.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Required Vulkan extension
- Could not acquire swapchain image
- DeviceWindowHandle cannot be null
- Only SDL is supported for the time being on Linux
- Unexpected error on Present
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/77e32d511163f549.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/Vulkan/SwapChainGraphicsPresenter.Vulkan.cs:557
if (surface != VkSurfaceKHR.Null)
{
GraphicsDevice.NativeInstanceApi.vkDestroySurfaceKHR(GraphicsDevice.NativeInstance, surface, null);
surface = VkSurfaceKHR.Null;
}
CreateSurface();
}
private unsafe void CreateSurface()
{
// Check for Window Handle parameter
if (Description.DeviceWindowHandle == null)
{
throw new ArgumentException("DeviceWindowHandle cannot be null");
}
// Validate surface extension support (not available with headless ICDs)
if (!GraphicsAdapterFactory.GetInstance(GraphicsDevice.IsDebugMode).HasSurfaceSupport)
throw new InvalidOperationException("Cannot create a swapchain: Vulkan surface extensions are not available. This may happen when using a headless ICD.");
// Create surface
#if STRIDE_UI_SDL
// iOS reuses the SDL surface-creation path (GameContextiOS inherits GameContextSDL);
// SDL's VulkanCreateSurface routes to VkMetalSurfaceCreateInfoEXT internally on iOS.
if (Description.DeviceWindowHandle.Context == Games.AppContextType.DesktopSDL
|| Description.DeviceWindowHandle.Context == Games.AppContextType.iOS)
{
var control = Description.DeviceWindowHandle.NativeWindow as SDL.Window;
Silk.NET.Core.Native.VkNonDispatchableHandle surfaceHandle = default;
SDL.Window.SDL.VulkanCreateSurface((Silk.NET.SDL.Window*)control.SdlHandle, new Silk.NET.Core.Native.VkHandle(GraphicsDevice.NativeInstance.Handle), ref surfaceHandle);
surface = new VkSurfaceKHR(surfaceHandle.Handle);
}
else
#endif
if (Platform.Type == PlatformType.Windows)
{
var controlHandle = Description.DeviceWindowHandle.Handle;View on GitHub (pinned to 96fad776d2)