run-llama/llama_index · error · ValueError
At least one of requests_per_minute or tokens_per_minute mus
Error message
At least one of requests_per_minute or tokens_per_minute must be set.
What it means
SlidingWindowRateLimiter is a pydantic model whose model_validator(mode='after') enforces that at least one limit is configured: requests_per_minute or tokens_per_minute. Creating one with both None raises ValueError, since a limiter with no cap is meaningless.
Source
Thrown at llama-index-core/llama_index/core/rate_limiter.py:291
gt=0,
)
token_burst: float = Field(
default=0.0,
ge=0.0,
description=(
"Additional tokens allowed as burst capacity within the sliding window. "
"Set to 0 for a strict cap."
),
)
_request_timestamps: Deque[float] = PrivateAttr(default_factory=deque)
_token_usage: Deque[Tuple[float, float]] = PrivateAttr(default_factory=deque)
_lock: threading.Lock = PrivateAttr(default_factory=threading.Lock)
@model_validator(mode="after")
def _check_limits(self) -> "SlidingWindowRateLimiter":
if self.requests_per_minute is None and self.tokens_per_minute is None:
raise ValueError(
"At least one of requests_per_minute or tokens_per_minute must be set."
)
return self
def _prune_request_timestamps(self, now: float) -> None:
"""Remove request timestamps outside the sliding window. Hold _lock."""
while (
self._request_timestamps
and self._request_timestamps[0] < now - _SLIDING_WINDOW_SECONDS
):
self._request_timestamps.popleft()
def _prune_token_usage(self, now: float) -> None:
"""Remove token usage entries outside the sliding window. Hold _lock."""
while (
self._token_usage
and self._token_usage[0][0] < now - _SLIDING_WINDOW_SECONDS
):View on GitHub (pinned to afd0fef371)
Solutions
- Set at least one limit, e.g. SlidingWindowRateLimiter(requests_per_minute=60)
- When loading from config, apply defaults for missing values before construction: rpm or 60, tpm or 100_000
- Validate configuration early (fail fast at startup) rather than deep inside a query run
Example fix
// before
rpm = os.getenv("RATE_LIMIT_RPM") # may be None
tpm = os.getenv("RATE_LIMIT_TPM") # may be None
limiter = SlidingWindowRateLimiter(requests_per_minute=rpm, tokens_per_minute=tpm)
// after
rpm = os.getenv("RATE_LIMIT_RPM")
tpm = os.getenv("RATE_LIMIT_TPM")
if rpm is None and tpm is None:
raise SystemExit("Configure RATE_LIMIT_RPM or RATE_LIMIT_TPM")
limiter = SlidingWindowRateLimiter(
requests_per_minute=float(rpm) if rpm else None,
tokens_per_minute=float(tpm) if tpm else None,
) Defensive patterns
Strategy: validation
Validate before calling
def build_limiter(rpm, tpm):
if rpm is None and tpm is None:
raise ValueError("Configure RATE_LIMIT_RPM or RATE_LIMIT_TPM before startup")
return SlidingWindowRateLimiter(
requests_per_minute=float(rpm) if rpm is not None else None,
tokens_per_minute=float(tpm) if tpm is not None else None,
) Prevention
- Fail fast on config: validate rate-limit settings at process start, not mid-query
- Give optional env-backed settings explicit defaults (e.g. rpm=60) when the variable is missing
- Never construct the limiter with both limits None from forwarded optional values
When it happens
Trigger: SlidingWindowRateLimiter() with no arguments, or explicitly passing requests_per_minute=None, tokens_per_minute=None (e.g. forwarding unset config values from env/CLI where missing settings become None).
Common situations: Building the limiter from optional config (os.getenv returning None) and passing both unset values through; instantiating to inspect defaults before deciding limits.
Related errors
- All agents must have a name in a multi-agent workflow
- All agents must have a description in a multi-agent workflow
- Initial state is not supported per-agent in AgentWorkflow
- Exactly one root agent must be provided
- Root agent {root_agent} not found in provided agents
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/e59ff82a3e995b9d.
Report an issue: GitHub.