{"record":{"id":"854117a7384a2107","repo":"stride3d/stride","slug":"tick-frequency-must-be-greater-than-zero","errorCode":null,"errorMessage":"Tick frequency must be greater than zero","messagePattern":"Tick frequency must be greater than zero","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core/Diagnostics/ProfilingState.cs","lineNumber":67,"sourceCode":"    /// <summary>\n    /// Gets the profiling key.\n    /// </summary>\n    /// <value>The profiling key.</value>\n    public ProfilingKey ProfilingKey { get; }\n\n    /// <summary>\n    /// A list of attributes (dimensions) associated with this profiling state.\n    /// </summary>\n    public TagList Attributes { get; }\n\n    /// <summary>\n    /// Gets or sets the TickFrequency used to convert <see cref=\"long\"/> timestamp to <see cref=\"TimeSpan\"/>.\n    /// By default for CPU events it's <see cref=\"Stopwatch.Frequency\"/> and for GPU events it's set by the rendering code.\"/>\n    /// </summary>\n    public long TickFrequency\n    {\n        get => tickFrequency;\n        set => tickFrequency = value > 0 ? value : throw new ArgumentOutOfRangeException(nameof(TickFrequency), \"Tick frequency must be greater than zero\");\n    }\n\n    /// <summary>\n    /// Checks if the profiling key is enabled and update this instance. See remarks.\n    /// </summary>\n    /// <remarks>\n    /// This can be used for long running profiling that are using markers and want to log markers if \n    /// the profiling was activated at runtime.\n    /// </remarks>\n    public void CheckIfEnabled()\n    {\n        isEnabled = Profiler.IsEnabled(ProfilingKey);\n    }\n\n    public void Dispose()\n    {\n        // Perform a Start event only if the profiling is running\n        if (!isEnabled) return;","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core/Diagnostics/ProfilingState.cs#L49-L85","documentation":"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.","triggerScenarios":"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).","commonSituations":"Custom GPU profiling integrations where the driver returns 0 frequency; copying CPU profiling code and forgetting to initialize frequency; int/float division producing 0.","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)"],"exampleFix":"// before\nstate.TickFrequency = gpuFrequency; // may be 0\n// after\nstate.TickFrequency = gpuFrequency > 0 ? gpuFrequency : Stopwatch.Frequency;","handlingStrategy":"validation","validationCode":"if (frequency <= 0) frequency = Stopwatch.Frequency;\nstate.TickFrequency = frequency;","typeGuard":"bool isValidTickFrequency(long v) => v > 0;","tryCatchPattern":"try { state.TickFrequency = frequency; }\ncatch (ArgumentOutOfRangeException) { state.TickFrequency = Stopwatch.Frequency; }","preventionTips":["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"],"tags":["profiling","argumentoutofrange","timestamps","gpu"],"backgroundTag":"argument-out-of-range","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}