scrapy/scrapy · error · ValueError
Interval must be greater than 0
Error message
Interval must be greater than 0
What it means
AsyncioLoopingCall.start() validates the interval argument and raises ValueError when interval <= 0, because scheduling a periodic call at zero or negative periods is meaningless (it would spin the loop).
Source
Thrown at scrapy/utils/asyncio.py:172
@property
def running(self) -> bool:
return self._start_time is not None
def start(self, interval: float, now: bool = True) -> None:
"""Start calling the function every *interval* seconds.
:param interval: The interval in seconds between calls.
:type interval: float
:param now: If ``True``, also call the function immediately.
:type now: bool
"""
if self.running:
raise RuntimeError("AsyncioLoopingCall already running")
if interval <= 0:
raise ValueError("Interval must be greater than 0")
self.interval = interval
self._start_time = time.monotonic()
if now:
self._call()
loop = asyncio.get_event_loop()
self._task = loop.create_task(self._loop())
def _to_sleep(self) -> float:
"""Return the time to sleep until the next call."""
assert self.interval is not None
assert self._start_time is not None
now = time.monotonic()
running_for = now - self._start_time
return self.interval - (running_for % self.interval)
async def _loop(self) -> None:
"""Run an infinite loop that calls the function periodically."""View on GitHub (pinned to 06af687662)
Solutions
- Pass a positive interval in seconds, e.g. lc.start(30)
- Validate/derive the interval defensively: interval = max(float(interval_setting), MIN_INTERVAL) or fail fast with a clear config error
- Check that settings keys used for the interval are actually set (self.settings.getfloat('MY_INTERVAL', 60))
Example fix
# before
lc.start(self.settings.getfloat('TICK_INTERVAL', 0)) # 0 -> ValueError
# after
lc.start(self.settings.getfloat('TICK_INTERVAL', 60)) Defensive patterns
Strategy: validation
Validate before calling
interval = self.settings.getfloat('TICK_INTERVAL', 60)
if interval <= 0:
raise ValueError(f'TICK_INTERVAL must be > 0, got {interval}') Prevention
- Always provide a positive default in settings.getfloat for interval keys
- Validate externally loaded config numbers before passing them to start()
When it happens
Trigger: Passing 0, a negative number, or a value computed to <= 0 (e.g. a settings-derived float that parsed to 0) as the interval argument of AsyncioLoopingCall.start().
Common situations: Reading an interval from settings where the key is missing and defaults to 0; float parsing of an empty string or invalid config value yielding 0; passing a timedelta object instead of seconds.
Related errors
- Invalid entry point {entry_point.name}
- AsyncioLoopingCall already running
- The AsyncioLoopingCall function must not return a coroutine
- Invalid value {value} for component {name}, please provide a
- crawler already set
AI-assisted analysis of scrapy/scrapy@06af687662 (2026-08-15).
Data as JSON: /api/errors/35219af219ef8007.
Report an issue: GitHub.