stride3d/stride · error · ArgumentNullException

graphicsDevice

Error message

graphicsDevice

What it means

The GraphicsResourceAllocator constructor requires a non-null GraphicsDevice instance; passing null throws ArgumentNullException with parameter name 'graphicsDevice'. The allocator stores the device and delegates to it for creating textures, buffers and query pools, so it cannot function without one.

Solutions

  1. Create the GraphicsDevice before constructing GraphicsResourceAllocator and pass the initialized instance.
  2. Assert the device is non-null at the call site to catch ordering issues early.
  3. Fix DI registration so a GraphicsDevice is actually provided.

Example fix

// before
var allocator = new GraphicsResourceAllocator(null);
// after
var allocator = new GraphicsResourceAllocator(graphicsDevice); // ensure graphicsDevice is initialized first
Defensive patterns

Strategy: validation

Validate before calling

if (graphicsDevice is null)
    throw new InvalidOperationException("GraphicsDevice must be created before the allocator");
var allocator = new GraphicsResourceAllocator(graphicsDevice);

Type guard

bool HasDevice(GraphicsDevice d) => d is not null;

Try / catch

try { allocator = new GraphicsResourceAllocator(device); }
catch (ArgumentNullException ex) { log.Error("null graphicsDevice", ex); throw; }

Prevention

When it happens

Trigger: Calling new GraphicsResourceAllocator(null) directly, or passing a GraphicsDevice field/property that is still null because the device was not yet created or initialization failed silently.

Common situations: Constructing the allocator before GraphicsDevice initialization in a game or render pipeline; a DI container injecting an unregistered (null) device; refactoring that reordered device creation after allocator creation.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Graphics/GraphicsResourceAllocator.cs:94

        private readonly object thisLock = new();

        private readonly TextureCache textureCache = [];      // Cache for Textures by their TextureDescription
        private readonly BufferCache bufferCache = [];        // Cache for Buffers by their BufferDescription
        private readonly QueryPoolCache queryPoolCache = [];  // Cache for QueryPools by their QueryPoolDescription

        private readonly CreateTextureDelegate createTextureDelegate;
        private readonly CreateBufferDelegate createBufferDelegate;
        private readonly CreateQueryPoolDelegate createQueryPoolDelegate;


        /// <summary>
        ///   Initializes a new instance of the <see cref="GraphicsResourceAllocator"/> class.
        /// </summary>
        /// <param name="graphicsDevice">The Graphics Device.</param>
        /// <exception cref="ArgumentNullException"><paramref name="graphicsDevice"/> is <see langword="null"/>.</exception>
        public GraphicsResourceAllocator(GraphicsDevice graphicsDevice)
        {
            GraphicsDevice = graphicsDevice ?? throw new ArgumentNullException(nameof(graphicsDevice));

            // We cache the delegates to avoid allocations on each call. They can't be static because they
            // can be overridden in derived classes
            createTextureDelegate = CreateTexture;
            createBufferDelegate = CreateBuffer;
            createQueryPoolDelegate = CreateQueryPool;
        }


        /// <summary>
        ///   Gets or sets the Graphics Device.
        /// </summary>
        private GraphicsDevice GraphicsDevice { get; }

        /// <summary>
        ///   Gets the services registry.
        /// </summary>
        public IServiceRegistry Services { get; private set; } // TODO: Never set, never read, remove this property?

View on GitHub (pinned to 96fad776d2)