walkor/workerman · error · RuntimeException

$timeInterval can not less than 0

Error message

$timeInterval can not less than 0

What it means

Timer::add() validates its first argument and rejects negative intervals: the event loop can only schedule callbacks at 'now or later'. A negative float means the computed deadline is in the past, which is almost always a bug in the caller's math.

Source

Thrown at src/Timer.php:144

        if (!self::$event) {
            pcntl_alarm(1);
            self::tick();
        }
    }

    /**
     * Add a timer.
     *
     * @param float $timeInterval
     * @param callable $func
     * @param null|array $args
     * @param bool $persistent
     * @return int
     */
    public static function add(float $timeInterval, callable $func, ?array $args = [], bool $persistent = true): int
    {
        if ($timeInterval < 0) {
            throw new RuntimeException('$timeInterval can not less than 0');
        }

        if ($args === null) {
            $args = [];
        }

        if (self::$event) {
            return $persistent ? self::$event->repeat($timeInterval, $func, $args) : self::$event->delay($timeInterval, $func, $args);
        }

        // If not workerman runtime just return.
        if (!Worker::getAllWorkers()) {
            throw new RuntimeException('Timer can only be used in workerman running environment');
        }

        if (empty(self::$tasks)) {
            pcntl_alarm(1);
        }

View on GitHub (pinned to 1391112a61)

Solutions

  1. Clamp the interval before scheduling: Timer::add(max(0.001, $interval), ...)
  2. Fix the computation: subtract once and re-check, or loop while ($next <= time()) $next += $period before computing the delta
  3. Make sure you pass a relative offset in seconds (float), never an absolute timestamp

Example fix

// before
$delta = $nextRun - time(); // can be -3 when the slot just passed
Timer::add($delta, fn() => run()); // throws '$timeInterval can not less than 0'

// after
$delta = max(0.001, $nextRun - time());
Timer::add($delta, fn() => run());
Defensive patterns

Strategy: validation

Validate before calling

$interval = $nextRun - time(); // computed
Timer::add(max(0.001, (float)$interval), $cb);

Prevention

When it happens

Trigger: Passing a computed delay that went negative, e.g. Timer::add($nextRunTimestamp - time(), ...) where the next run already passed; passing -1 as an 'immediate' flag; passing an absolute Unix timestamp instead of an offset in seconds.

Common situations: Cron-style schedulers computing 'seconds until next minute/hour' with a race that yields -1; mixing time() and microtime(true) units; DST or clock-skew corrections making a stored deadline earlier than now.

Related errors


AI-assisted analysis of walkor/workerman@1391112a61 (2026-08-21). Data as JSON: /api/errors/fdafc54794cb554b. Report an issue: GitHub.