stride3d/stride · error · ArgumentNullException

array

Error message

array

What it means

Argument-null validation in ArrayPool.Free: the array being returned to the pool is null. There is no pooled object to release for a null reference, so the method throws ArgumentNullException named 'array'. (Note the sibling Allocate method similarly guards size with 'Must be positive'.)

Solutions

  1. Initialize buffers to Array.Empty<T>() instead of null
  2. Guard Free calls with a null check
  3. Ensure allocation succeeded before scheduling the free

Example fix

// before
arrayPool.Free(buffer); // buffer may be null
// after
if (buffer != null) arrayPool.Free(buffer);
Defensive patterns

Strategy: validation

Validate before calling

if (buffer != null)
    pool.Free(buffer);

Prevention

When it happens

Trigger: Calling Free(null) after a failed allocation path or when the buffer variable was never assigned.

Common situations: Cleanup/finally blocks in particle sorting code freeing buffers that were never allocated.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Particles/Sorters/ArrayPool.cs:31

        public virtual void Clear()
        {
            _pool.Clear();
        }

        public virtual T[] Allocate(int size)
        {
            if (size < 0) throw new ArgumentOutOfRangeException(nameof(size), "Must be positive.");

            if (size == 0) return Empty;

            Stack<T[]> candidates;
            return _pool.TryGetValue(size, out candidates) && candidates.Count > 0 ? candidates.Pop() : new T[size];
        }

        public virtual void Free(T[] array)
        {
            if (array == null) throw new ArgumentNullException(nameof(array));

            if (array.Length == 0) return;

            Stack<T[]> candidates;
            if (!_pool.TryGetValue(array.Length, out candidates))
                _pool.Add(array.Length, candidates = new Stack<T[]>());
            candidates.Push(array);
        }
    }

    public class ConcurrentArrayPool<T> : ArrayPool<T> where T : struct
    {
        public override T[] Allocate(int size)
        {
            lock (this)
            {
                return base.Allocate(size);
            }

View on GitHub (pinned to 96fad776d2)