# What does the VARTA error `rate_limit_exceeded` mean?

Too many requests, or too much spend, for your tenant right now.


**HTTP status:** `429` &nbsp;·&nbsp; **Type:** `rate_limit_error`

## What it means

Too many requests, or too much spend, for your tenant right now.

## What causes it

Reachable today from `POST /v1/calls`, which delegates to session start: the platform checks each tenant's daily spend budget before preparing a call and raises this when it's exceeded (`backend/app/routers/sessions.py`, `backend/app/security/abuse_guard/limiter.py`). It is also the fallback code for any unrecognised 429.

**The spend-budget check is off in the default configuration.** `check_budget` returns immediately unless `settings.tenant_daily_budget_inr > 0`, and that setting defaults to `0.0` — meaning unlimited (`backend/app/security/abuse_guard/limiter.py:83-89`, `backend/app/core/config.py:48`). So on a default instance this error is not reachable from the spend path at all; you will only see it as the generic fallback for an unrecognised 429. An operator has to set a positive daily budget for it to fire.

## What to do

**There is no `Retry-After` header on this response.** The limiter does set one when it raises (`Retry-After: 3600`, `backend/app/security/abuse_guard/limiter.py:95-96`), but the `/v1` error layer rebuilds the response headers from scratch and emits only `X-Request-Id` — the original headers, `Retry-After` included, are discarded (`backend/app/api/v1/errors.py:160-173`, called from `:276-281`). Do not write a client that waits on that header; it will read `null` and, if you treat that as "retry now", you will hot-loop.

Back off on a schedule of your own instead — exponential backoff with jitter is the right default. A spend-budget denial specifically clears at the next UTC day boundary, so there is no value in retrying it faster than that once you have confirmed that is the cause (read `message`).
