stride3d/stride · error · ArgumentOutOfRangeException
Tick frequency must be greater than zero
Error message
Tick frequency must be greater than zero
What it means
ProfilingState.TickFrequency converts raw timestamps to TimeSpan and its setter enforces a strictly positive value; assigning 0 or a negative long throws ArgumentOutOfRangeException. GPU tick frequencies are set by rendering code, so a failed/absent GPU query can leave an invalid value that gets pushed here.
Solutions
- Only assign Stopwatch.Frequency or a queried positive GPU frequency
- Check for 0 before assignment and fall back to Stopwatch.Frequency
- Clamp: state.TickFrequency = Math.Max(1, queriedFrequency)
Example fix
// before state.TickFrequency = gpuFrequency; // may be 0 // after state.TickFrequency = gpuFrequency > 0 ? gpuFrequency : Stopwatch.Frequency;
Defensive patterns
Strategy: validation
Validate before calling
if (frequency <= 0) frequency = Stopwatch.Frequency; state.TickFrequency = frequency;
Type guard
bool isValidTickFrequency(long v) => v > 0;
Try / catch
try { state.TickFrequency = frequency; }
catch (ArgumentOutOfRangeException) { state.TickFrequency = Stopwatch.Frequency; } Prevention
- Initialize GPU frequencies from a successful query before use
- Fallback to Stopwatch.Frequency when a query fails or returns 0
- Never assign computed values that can round to 0
When it happens
Trigger: profileState.TickFrequency = 0 (or negative) in custom profiling code, or GPU backend code that assigns an unqueried/failed frequency (e.g. 0 from an uninitialized timestamp-frequency query).
Common situations: Custom GPU profiling integrations where the driver returns 0 frequency; copying CPU profiling code and forgetting to initialize frequency; int/float division producing 0.
Related errors
- Couldn't transfer frame data from GPU to CPU
- DoF configuration needs at least one blur level!
- Expecting value >= 0
- Expecting value >= 1
- Invalid 'text' argument
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/854117a7384a2107.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core/Diagnostics/ProfilingState.cs:67
/// <summary>
/// Gets the profiling key.
/// </summary>
/// <value>The profiling key.</value>
public ProfilingKey ProfilingKey { get; }
/// <summary>
/// A list of attributes (dimensions) associated with this profiling state.
/// </summary>
public TagList Attributes { get; }
/// <summary>
/// Gets or sets the TickFrequency used to convert <see cref="long"/> timestamp to <see cref="TimeSpan"/>.
/// By default for CPU events it's <see cref="Stopwatch.Frequency"/> and for GPU events it's set by the rendering code."/>
/// </summary>
public long TickFrequency
{
get => tickFrequency;
set => tickFrequency = value > 0 ? value : throw new ArgumentOutOfRangeException(nameof(TickFrequency), "Tick frequency must be greater than zero");
}
/// <summary>
/// Checks if the profiling key is enabled and update this instance. See remarks.
/// </summary>
/// <remarks>
/// This can be used for long running profiling that are using markers and want to log markers if
/// the profiling was activated at runtime.
/// </remarks>
public void CheckIfEnabled()
{
isEnabled = Profiler.IsEnabled(ProfilingKey);
}
public void Dispose()
{
// Perform a Start event only if the profiling is running
if (!isEnabled) return;View on GitHub (pinned to 96fad776d2)