stride3d/stride · error · ArgumentNullException

graphicsDevice

Error message

graphicsDevice

What it means

FontSystem.Load requires a GraphicsDevice to create GPU-backed font resources and throws ArgumentNullException when it is null. It also needs a file provider service to construct the FontManager, so a null device means the font system cannot be initialized at all.

Solutions

  1. Create/initialize the GraphicsDevice before calling FontSystem.Load and pass the real instance
  2. Defer font system initialization to a point after the game's device is ready (e.g. after SceneSystem setup)
  3. In tests, mock or skip FontSystem.Load since fonts require a device

Example fix

// before
fontSystem.Load(game.GraphicsDevice, services); // GraphicsDevice not yet created
// after
var device = game.GraphicsDevice ?? throw new InvalidOperationException("Graphics not initialized yet");
fontSystem.Load(device, services);
Defensive patterns

Strategy: type-guard

Validate before calling

if (graphicsDevice is null || graphicsDevice.IsDisposed)
    throw new InvalidOperationException("Valid GraphicsDevice required before FontSystem.Load");

Type guard

bool DeviceReady(GraphicsDevice d) => d is not null && !d.IsDisposed;

Try / catch

try { fontSystem.Load(device, fileProvider); }
catch (ArgumentNullException)
{
    log.Error("FontSystem.Load called before GraphicsDevice was created");
}

Prevention

When it happens

Trigger: Calling fontSystem.Load(null, fileProviderService) before the game's GraphicsDevice is created, or in a headless/tooling context where no device exists.

Common situations: Initializing font services in a script constructor that runs before Game.GraphicsDevice is assigned; unit tests exercising font code without a device; ordering mistakes where fonts load before engine init.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Graphics/Font/FontSystem.cs:58

        /// </remarks>
        public RuntimeFontProvider RuntimeFonts { get; private set; }

        /// <summary>
        /// Create a new instance of <see cref="FontSystem" /> base on the provided <see cref="Stride.Graphics.GraphicsDevice" />.
        /// </summary>
        public FontSystem()
        {
        }

        /// <summary>
        /// Load this system.
        /// </summary>
        /// <param name="graphicsDevice">The graphics device.</param>
        /// <exception cref="System.ArgumentNullException">graphicsDevice</exception>
        public void Load(GraphicsDevice graphicsDevice, IDatabaseFileProviderService fileProviderService)
        {
            // TODO possibly load cached character bitmaps from the disk
            if (graphicsDevice == null) throw new ArgumentNullException("graphicsDevice");
            GraphicsDevice = graphicsDevice;
            FontManager = new FontManager(fileProviderService);
            FontCacheManager = new FontCacheManager(this);
            RuntimeFonts = new RuntimeFontProvider(this);
        }

        /// <summary>
        /// Loads a runtime-registered font by name.
        /// This bypasses the content pipeline entirely.
        /// </summary>
        /// <param name="fontName">The registered font name. If the font is not registered, the method returns <c>null</c>.</param>
        /// <param name="defaultSize">The default font size in pixels.</param>
        /// <param name="style">The font style.</param>
        /// <returns>A <see cref="SpriteFont"/> instance if the font is registered; otherwise, <c>null</c>.</returns>
        public SpriteFont? LoadRuntimeFont(string fontName, float defaultSize = 16f, FontStyle style = FontStyle.Regular)
        {
            if (!RuntimeFonts.IsRegistered(fontName, style))
                return null;

View on GitHub (pinned to 96fad776d2)