laravel/framework · error · InvalidArgumentException

Timeout must be greater than zero.

Error message

Timeout must be greater than zero.

What it means

Thrown by timeout() when the supplied integer of seconds is <= 0 (and not null). The setter configures the per-query execution timeout; zero or negative durations are meaningless for SQL statement timeouts and would either no-op or be rejected by the driver. Passing null explicitly disables the timeout and is allowed.

Source

Thrown at src/Illuminate/Database/Query/Builder.php:3381

     * @return $this
     */
    public function sharedLock()
    {
        return $this->lock(false);
    }

    /**
     * Set a query execution timeout in seconds.
     *
     * @param  int|null  $seconds
     * @return $this
     *
     * @throws InvalidArgumentException
     */
    public function timeout(?int $seconds): static
    {
        if ($seconds !== null && $seconds <= 0) {
            throw new InvalidArgumentException('Timeout must be greater than zero.');
        }

        $this->timeout = $seconds;

        return $this;
    }

    /**
     * Register a closure to be invoked before the query is executed.
     *
     * @return $this
     */
    public function beforeQuery(callable $callback)
    {
        $this->beforeQueryCallbacks[] = $callback;

        return $this;
    }

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Pass a positive integer: `->timeout(30)`.
  2. Pass null to disable: `->timeout(null)`.
  3. Guard config-driven values: `->timeout($cfg > 0 ? $cfg : null)`.
  4. Validate before calling: `if ($seconds !== null && $seconds <= 0) abort(400, 'bad timeout');`.

Example fix

// before
$query->timeout((int) config('app.query_timeout', 0))->get();
// when default is 0 => Timeout must be greater than zero.

// after
$secs = (int) config('app.query_timeout', 0);
$query->timeout($secs > 0 ? $secs : null)->get();
Defensive patterns

Strategy: validation

Validate before calling

if ($seconds !== null && $seconds <= 0) {
    $seconds = null; // or throw
}
$query->timeout($seconds);

Type guard

function isValidTimeout(?int $s): bool
{
    return $s === null || $s > 0;
}

Try / catch

// Validate before calling; catching an InvalidArgumentException here adds noise.

Prevention

When it happens

Trigger: `->timeout(0)`, `->timeout(-1)`. Computing timeout from a config value that defaults to 0. Subtracting a large offset that goes negative: `->timeout($budget - $elapsed)`.

Common situations: Config-driven timeouts where the env var is unset and casts to 0; adaptive timeout budgets that go negative under load; tests passing 0 expecting 'no timeout' semantics.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/e84c1e5d93983114.json. Report an issue: GitHub.