{"record":{"id":"01c7a9671bc63a8f","repo":"SignalR/SignalR","slug":"value-must-be-greater-than-zero","errorCode":null,"errorMessage":"Value must be greater than zero.","messagePattern":"Value must be greater than zero\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"samples/Microsoft.AspNet.SignalR.Samples/Hubs/RealtimeBroadcast/HighFrequencyTimer.cs","lineNumber":51,"sourceCode":"        public HighFrequencyTimer(double fps, Action<long> callback)\n            : this(fps, callback, null, null, null)\n        {\n            \n        }\n\n        /// <summary>\n        /// Creates a new instance of a high-resolution FPS timer.\n        /// </summary>\n        /// <param name=\"fps\">The desired frame rate per second.</param>\n        /// <param name=\"callback\">The callback to be invoked on each frame.</param>\n        /// <param name=\"started\">The callback to be invoked when the timer enters the running state.</param>\n        /// <param name=\"stopped\">The callback to be invoked when the timer enters the stopped state.</param>\n        /// <param name=\"actualFpsUpdate\">The callback to invoked to receive updates of the actual frame rate.</param>\n        public HighFrequencyTimer(double fps, Action<long> callback, Action started, Action stopped, Action<int> actualFpsUpdate)\n        {\n            if (fps <= 0)\n            {\n                throw new ArgumentException(\"Value must be greater than zero.\", \"fps\");\n            }\n\n            if (callback == null)\n            {\n                throw new ArgumentNullException(\"callback\");\n            }\n\n            _fps = fps;\n            _callback = callback;\n            _started = started ?? (() => { });\n            _stopped = stopped ?? (() => { });\n            _actualFpsUpdate = actualFpsUpdate ?? (_ => { });\n        }\n\n        public bool Start()\n        {\n            // Try to move to starting state\n            if (Interlocked.CompareExchange(ref _state, 1, 0) != 0)","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/SignalR/SignalR/blob/693053b89a9e1f5ce819e3233ed159a6409de22b/samples/Microsoft.AspNet.SignalR.Samples/Hubs/RealtimeBroadcast/HighFrequencyTimer.cs#L33-L69","documentation":"Thrown by the HighFrequencyTimer constructor when the requested frames-per-second value is less than or equal to zero. The timer drives a fixed-interval callback loop, so a non-positive rate is mathematically invalid (it would imply an infinite or negative period).","triggerScenarios":"Constructing new HighFrequencyTimer(fps, ...) with fps <= 0. Common when fps is read from a config value, a UI slider defaulting to 0, or computed as a difference that can go negative.","commonSituations":"Uninitialized config field defaulting to 0; a frame-rate slider clamped at its minimum of 0; a calculation like (baseFps - overhead) producing 0 or negative under load; copy-paste from a value in different units.","solutions":["Validate fps > 0 before constructing the timer, clamping to a sane default (e.g. 30 or 60) when invalid.","Fix the source config/UI to never offer a non-positive rate.","Wrap the constructor call in try/catch ArgumentException to fall back to a default rate with a logged warning."],"exampleFix":"// before\nvar timer = new HighFrequencyTimer(fpsFromConfig, cb, started, stopped, fpsUpdate);\n\n// after\nvar fps = fpsFromConfig > 0 ? fpsFromConfig : 30;\nvar timer = new HighFrequencyTimer(fps, cb, started, stopped, fpsUpdate);","handlingStrategy":"validation","validationCode":"if (fps <= 0) throw new ArgumentOutOfRangeException(nameof(fps), \"fps must be positive\");\n// or clamp:\nvar safeFps = fps > 0 ? fps : 30;","typeGuard":null,"tryCatchPattern":"try { var t = new HighFrequencyTimer(fps, cb, s, st, u); }\ncatch (ArgumentException ex) when (ex.ParamName == \"fps\") {\n    logger.Warn(\"Invalid fps {0}, using default\", fps);\n    timer = new HighFrequencyTimer(30, cb, s, st, u);\n}","preventionTips":["Validate numeric config inputs at load time, not at construction time.","Clamp UI sliders to a positive minimum.","Unit-test the constructor boundary (0, negative, very large)."],"tags":["signalr","realtime","validation","configuration"],"backgroundTag":null,"analyzedSha":"693053b89a9e1f5ce819e3233ed159a6409de22b","analyzedAt":"2026-08-13T22:23:59.793Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}