stride3d/stride · error · InvalidOperationException
Capacity must be a power of two
Error message
Capacity must be a power of two
What it means
The same Deque<T> capacity constructor further requires the capacity to be a power of two (1, 2, 4, 8, ...) so that index wrapping can use a bitmask (mask = capacity - 1). When int.IsPow2(capacity) is false it throws InvalidOperationException. Despite the exception type, this is invalid input: capacities like 3, 5, 100 are simply not supported by the ring-buffer layout.
Solutions
- Round up to the next power of two: BitOperations.RoundUpToPowerOf2((uint)capacity).
- Use an explicit power-of-two constant (1, 2, 4, 8, 16, ...).
- Wrap construction in a helper that validates/normalizes capacity once.
Example fix
// before var deque = new Deque<Entity>(100); // throws: 100 is not a power of two // after var cap = Math.Max(1, (int)System.Numerics.BitOperations.RoundUpToPowerOf2((uint)100)); var deque = new Deque<Entity>(cap); // 128
Defensive patterns
Strategy: validation
Validate before calling
int capacity = requested < 1 ? 1 : (int)System.Numerics.BitOperations.RoundUpToPowerOf2((uint)requested); var deque = new Deque<Entity>(capacity); // always a valid power of two
Try / catch
try
{
var deque = new Deque<Entity>(capacity);
}
catch (InvalidOperationException)
{
var deque2 = new Deque<Entity>(System.Numerics.BitOperations.RoundUpToPowerOf2((uint)Math.Max(1, capacity)));
} Prevention
- Always round requested capacities up with BitOperations.RoundUpToPowerOf2.
- Remember Deque<T> capacity semantics differ from List<T>/Queue<T>, which accept any value.
- Centralize deque construction in one helper that normalizes capacity.
When it happens
Trigger: new Deque<T>(100) or any non-power-of-two literal; sizing the deque to an expected item count without rounding up; translating code from List<T>/Queue<T> whose capacity constructors accept arbitrary values.
Common situations: Pre-allocating 'expected count' capacities measured empirically (e.g. 100); porting generic queue code to Stride's Deque; configuration values written by hand without the power-of-two constraint in mind.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Capacity must be greater than 0.
- The given type does not implement IObjectFactory/
- The given item does not validate the collection constraint.
- Array is null
- Destination array cannot be null.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/785c04f3829d733a.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core/Collections/Dequeue.cs:77
/// </summary>
private int offset;
/// <summary>
/// Used to wrap around indices when incrementing outside buffer range
/// </summary>
private int mask;
/// <summary>
/// Initializes a new instance of the <see cref="Deque<T>"/> class with the specified capacity.
/// </summary>
/// <param name="capacity">The initial capacity. Must be a power of two greater than <c>0</c>.</param>
public Deque(int capacity)
{
if (capacity < 1)
throw new ArgumentOutOfRangeException(nameof(capacity), "Capacity must be greater than 0.");
if (int.IsPow2(capacity) == false)
throw new InvalidOperationException("Capacity must be a power of two");
buffer = new T[capacity];
mask = buffer.Length - 1;
}
/// <summary>
/// Initializes a new instance of the <see cref="Deque<T>"/> class.
/// </summary>
public Deque()
: this(DefaultCapacity)
{
}
#region GenericListImplementations
/// <summary>
/// Gets a value indicating whether this list is read-only. This implementation always returns <c>false</c>.
/// </summary>View on GitHub (pinned to 96fad776d2)