Skip to content

Provider free-tier exhausted

When you shop around providers at the prototype stage, each has its own trial credits — and they run out silently. From the outside it looks like “the model suddenly stopped answering”: the code fails with insufficient_quota or 402 Payment Required, and you spend half an hour thinking you broke the prompt.

Separate this error from ordinary failures and send a push exactly once — with the name of the provider that ran out.

Catch specifically “quota exhausted”, not any error

Section titled “Catch specifically “quota exhausted”, not any error”

It’s important not to confuse “credits ran out” (fixed by topping up) with 429 (fixed by waiting). For providers these are different codes/types — we check precisely.

import os, requests
import openai, anthropic
NOTIFLY_URL = os.environ["NOTIFLY_URL"]
NOTIFLY_TOKEN = os.environ["NOTIFLY_TOKEN"]
def notify(title, msg, prio):
requests.post(f"{NOTIFLY_URL}/message",
params={"token": NOTIFLY_TOKEN},
json={"title": title, "message": msg, "priority": prio},
timeout=5)
def _alerted_once(provider):
"""Per-provider flag: the exhausted-trial alert is sent once."""
flag = f"/tmp/free-tier-{provider}.flag"
if os.path.exists(flag):
return True
open(flag, "w").close()
return False
def is_quota_exhausted(exc):
"""True only for "credits/quota ran out", not for rate-limit."""
# OpenAI: 429 with code == "insufficient_quota" (yes, the same status as rate-limit)
if isinstance(exc, openai.RateLimitError):
code = (getattr(exc, "code", None)
or (exc.body or {}).get("code") if getattr(exc, "body", None) else None)
return code == "insufficient_quota"
# Anthropic and many OpenAI-compatible APIs: 402 Payment Required
status = getattr(exc, "status_code", None)
return status == 402
def guard(provider, call):
"""Run the call; on quota exhaustion — push once and re-raise."""
try:
return call()
except Exception as e:
if is_quota_exhausted(e) and not _alerted_once(provider):
notify(
f"🪙 {provider}: кончился free-tier",
f"Ошибка квоты у {provider}. Пополните счёт или переключите провайдера.",
priority=7,
)
raise
# usage
oai = openai.OpenAI()
resp = guard("openai", lambda: oai.chat.completions.create(
model="gpt-4o-mini", messages=[{"role": "user", "content": "ping"}]))

OpenAI’s insufficient_quota arrives under the same status 429 as rate-limit — so looking at the HTTP code alone isn’t enough, you need the code. A per-provider flag file guarantees that after topping up you won’t get the same alert a hundred times in a row.

If you run the same prompt across several APIs at once, wrap each in its own guard(provider, ...) — and the very first push tells you exactly whose credits ran out, without digging through logs. After topping up, delete the flag file (rm /tmp/free-tier-openai.flag) so the alert becomes possible again.

  • the provider name and model;
  • the exact error code (insufficient_quota / 402) — to tell it apart from 429;
  • a direct link to that provider’s billing page;
  • a reminder to delete the flag file after topping up.