stride3d/stride · error · ArgumentOutOfRangeException
Must be positive.
Error message
Must be positive.
What it means
ArrayPool.Allocate throws ArgumentOutOfRangeException when 'size' is negative. The pool keys cached arrays by exact size, so negative sizes are meaningless; note that 0 is explicitly allowed and returns the shared empty array, despite the message saying 'Must be positive.'
Solutions
- Clamp the size argument to >= 0 before calling Allocate
- Fix the upstream calculation producing the negative size
- Use Math.Max(0, size) at the call site
Example fix
// before var buffer = arrayPool.Allocate(particleCount - removed); // after var buffer = arrayPool.Allocate(Math.Max(0, particleCount - removed));
Defensive patterns
Strategy: validation
Validate before calling
if (size >= 0)
var buffer = pool.Allocate(size); Prevention
- Clamp computed sizes with Math.Max(0, n)
- Validate particle counts before computing buffer sizes
- Beware of subtractions that can underflow
When it happens
Trigger: Calling Allocate with a negative computed size, e.g. from a particle count or subtraction that went below zero (count - removedCount where removed > count).
Common situations: Particle sorter code computing buffer sizes from dynamic particle counts that underflow or are fed invalid data.
Related errors
- array
- A negative number of mip maps is not allowed.
- ArgumentOutOfRangeException
- ArgumentOutOfRangeException
- ArgumentOutOfRangeException
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/afaff6a961eee278.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Particles/Sorters/ArrayPool.cs:21
using System;
using System.Collections.Generic;
namespace Stride.Particles.Sorters
{
public class ArrayPool<T> where T : struct
{
private readonly Dictionary<int, Stack<T[]>> _pool = new Dictionary<int, Stack<T[]>>();
public static readonly T[] Empty = Array.Empty<T>();
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);
}View on GitHub (pinned to 96fad776d2)