SignalR/SignalR · error · ArgumentException

Value must be greater than zero.

Error message

Value must be greater than zero.

What it means

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).

Source

Thrown at samples/Microsoft.AspNet.SignalR.Samples/Hubs/RealtimeBroadcast/HighFrequencyTimer.cs:51

        public HighFrequencyTimer(double fps, Action<long> callback)
            : this(fps, callback, null, null, null)
        {
            
        }

        /// <summary>
        /// Creates a new instance of a high-resolution FPS timer.
        /// </summary>
        /// <param name="fps">The desired frame rate per second.</param>
        /// <param name="callback">The callback to be invoked on each frame.</param>
        /// <param name="started">The callback to be invoked when the timer enters the running state.</param>
        /// <param name="stopped">The callback to be invoked when the timer enters the stopped state.</param>
        /// <param name="actualFpsUpdate">The callback to invoked to receive updates of the actual frame rate.</param>
        public HighFrequencyTimer(double fps, Action<long> callback, Action started, Action stopped, Action<int> actualFpsUpdate)
        {
            if (fps <= 0)
            {
                throw new ArgumentException("Value must be greater than zero.", "fps");
            }

            if (callback == null)
            {
                throw new ArgumentNullException("callback");
            }

            _fps = fps;
            _callback = callback;
            _started = started ?? (() => { });
            _stopped = stopped ?? (() => { });
            _actualFpsUpdate = actualFpsUpdate ?? (_ => { });
        }

        public bool Start()
        {
            // Try to move to starting state
            if (Interlocked.CompareExchange(ref _state, 1, 0) != 0)

View on GitHub (pinned to 693053b89a)

Solutions

  1. Validate fps > 0 before constructing the timer, clamping to a sane default (e.g. 30 or 60) when invalid.
  2. Fix the source config/UI to never offer a non-positive rate.
  3. Wrap the constructor call in try/catch ArgumentException to fall back to a default rate with a logged warning.

Example fix

// before
var timer = new HighFrequencyTimer(fpsFromConfig, cb, started, stopped, fpsUpdate);

// after
var fps = fpsFromConfig > 0 ? fpsFromConfig : 30;
var timer = new HighFrequencyTimer(fps, cb, started, stopped, fpsUpdate);
Defensive patterns

Strategy: validation

Validate before calling

if (fps <= 0) throw new ArgumentOutOfRangeException(nameof(fps), "fps must be positive");
// or clamp:
var safeFps = fps > 0 ? fps : 30;

Try / catch

try { var t = new HighFrequencyTimer(fps, cb, s, st, u); }
catch (ArgumentException ex) when (ex.ParamName == "fps") {
    logger.Warn("Invalid fps {0}, using default", fps);
    timer = new HighFrequencyTimer(30, cb, s, st, u);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of SignalR/SignalR@693053b89a (2026-08-13). Data as JSON: /api/errors/01c7a9671bc63a8f. Report an issue: GitHub.