stride3d/stride · error · InvalidOperationException

Unexpected null GraphicsDevice

Error message

Unexpected null GraphicsDevice

What it means

After GraphicsDeviceManager attempts to create the device (CreateDevice), it validates that the GraphicsDevice property is non-null before reading presentation parameters; a null here means device creation silently failed to assign the device, violating an internal invariant. This is a defensive check surfaced when CreateDevice or the factory path did not actually produce a device.

Solutions

  1. Inspect earlier logs/inner exceptions: fix the underlying CreateDevice/IGraphicsDeviceFactory failure so it actually produces a GraphicsDevice.
  2. Ensure a stock factory (e.g. DeviceFactorySDL / platform default) is registered rather than a custom stub that returns without creating a device.
  3. Update Stride — this null state can result from platform bugs fixed in later versions.

Example fix

// before
public class MyFactory : IGraphicsDeviceFactory // never assigns GraphicsDevice
// after
// use the platform factory:
game.Services.AddService<IGraphicsDeviceFactory>(new DeviceFactorySDL());
Defensive patterns

Strategy: try-catch

Validate before calling

if (game.Services.GetService<IGraphicsDeviceFactory>() is not DeviceFactorySDL && customFactory is null)
    throw new InvalidOperationException("Register a real IGraphicsDeviceFactory");

Type guard

bool DeviceCreated(GameBase g) => g.GraphicsDevice != null;

Try / catch

try { gdm.ApplyChanges(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Unexpected null GraphicsDevice"))
{
    logger.LogError(ex, "Device creation did not produce a GraphicsDevice");
    throw;
}

Prevention

When it happens

Trigger: Code path in GraphicsDeviceManager (e.g. changing device/fullscreen toggling) sets needToCreateNewDevice and calls CreateDevice, yet GraphicsDevice remains null afterwards — e.g. CreateDevice's factory returned without constructing the device, or a prior creation failure was swallowed.

Common situations: Custom IGraphicsDeviceFactory implementations that don't set the device, partially failed device creation with earlier exceptions caught upstream, race conditions during window creation/ recreation, or platform factory mismatches.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/73d27f4ac44ec17b. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Games/GraphicsDeviceManager.cs:1243

                                GraphicsDevice.Presenter.Resize(newWidth, newHeight, newFormat);

                                // Change full screen if needed
                                GraphicsDevice.Presenter.IsFullScreen = graphicsDeviceInformation.PresentationParameters.IsFullScreen;

                                needToCreateNewDevice = false;
                            }
                            catch { /* Ignore any exception */ }
                        }
                    }

                    // If we still need to create a device, then we need to create it
                    if (needToCreateNewDevice)
                    {
                        CreateDevice(graphicsDeviceInformation);
                    }

                    if (GraphicsDevice is null)
                        throw new InvalidOperationException("Unexpected null GraphicsDevice");

                    var presentationParameters = GraphicsDevice.Presenter.Description;
                    isReallyFullScreen = presentationParameters.IsFullScreen;

                    if (presentationParameters.BackBufferWidth != 0)
                        width = presentationParameters.BackBufferWidth;
                    if (presentationParameters.BackBufferHeight != 0)
                        height = presentationParameters.BackBufferHeight;
                    deviceSettingsChanged = false;
                }
                finally
                {
                    // Notify the game Window that the screen device change is over
                    if (isBeginScreenDeviceChange)
                    {
                        game.Window.EndScreenDeviceChange(width, height);
                        game.Window.SetIsReallyFullscreen(isReallyFullScreen);
                    }

View on GitHub (pinned to 96fad776d2)