stride3d/stride · error · ArgumentOutOfRangeException
Thread count must be positive.
Error message
Thread count must be positive.
What it means
DispatcherWrapper's constructor validates that the number of worker threads dispatched per invocation is strictly positive, since it sizes WorkerBufferPools and schedules work across threads. A zero or negative threadCount makes dispatch meaningless and would corrupt pool sizing, so it throws ArgumentOutOfRangeException.
Solutions
- Pass at least 1 thread: new DispatcherWrapper(Math.Max(1, threadCount));
- Fix the thread-count source so it yields a positive value (e.g. Environment.ProcessorCount).
- Use the default constructor path / library defaults instead of hand-rolling a dispatcher.
Example fix
// before var dispatcher = new DispatcherWrapper(config.ThreadCount); // 0 // after var dispatcher = new DispatcherWrapper(Math.Max(1, config.ThreadCount));
Defensive patterns
Strategy: validation
Validate before calling
int threadCount = Math.Max(1, configuredThreadCount); var dispatcher = new DispatcherWrapper(threadCount);
Try / catch
try { d = new DispatcherWrapper(cfg.ThreadCount); } catch (ArgumentOutOfRangeException) { d = new DispatcherWrapper(Environment.ProcessorCount); } Prevention
- Clamp config-derived thread counts with Math.Max(1, value)
- Default to Environment.ProcessorCount when config is missing
- Validate numeric settings after deserialization
When it happens
Trigger: Constructing new DispatcherWrapper(0) or with a negative value, typically from a thread-count setting read from config/environment that defaulted to 0 or wasn't initialized.
Common situations: Environment.ProcessorCount returning unexpectedly, config parsing producing 0, or custom BepuSimulation threading setup passing an unset variable.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Duration provided must be greater than zero
- Cannot dispose while a job is in flight
- 's must be finite and greater than zero
- is not supported in height type. Or . doesn't match .
- . is not enough to copy.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/02170dc6bbfe8631.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.BepuPhysics/Stride.BepuPhysics/BepuSimulation.cs:1117
private volatile bool _disposed;
/// <inheritdoc/>
public WorkerBufferPools WorkerPools { get; private set; }
/// <inheritdoc/>
public void* UnmanagedContext => _unmanagedContext;
/// <inheritdoc/>
public object? ManagedContext => _managedContext;
/// <summary>
/// Creates a new thread dispatcher with the given number of threads.
/// </summary>
/// <param name="threadCount">Number of threads to dispatch on each invocation.</param>
/// <param name="threadPoolBlockAllocationSize">Size of memory blocks to allocate for thread pools.</param>
public DispatcherWrapper(int threadCount, int threadPoolBlockAllocationSize = 16384)
{
if (threadCount <= 0)
throw new ArgumentOutOfRangeException(nameof(threadCount), "Thread count must be positive.");
_threadCount = threadCount;
WorkerPools = new WorkerBufferPools(threadCount, threadPoolBlockAllocationSize);
}
private void DispatchThread(int workerIndex)
{
switch (_workerType)
{
case WorkerType.Managed: _managedWorker!(workerIndex); break;
case WorkerType.Unmanaged: _unmanagedWorker(workerIndex, this); break;
}
}
private void SignalThreads(int maximumWorkerCount)
{
int workersToSignal = maximumWorkerCount < _threadCount ? maximumWorkerCount : _threadCount;
Dispatcher.ForBatched(workersToSignal, new Job(this));
}View on GitHub (pinned to 96fad776d2)