ब्लॉग पर वापस जाएं

समस्या निवारणगाइड

AI API से 429 Too Many Requests: backoff के साथ रीट्राई

AI API से आने वाले 429 का क्या अर्थ है और इसे कैसे संभालें: jitter के साथ exponential backoff, Retry-After, और एजेंट समवर्तीता, Python और JavaScript कोड के साथ।

CheapTokens Team द्वाराप्रकाशित अपडेट किया गया 10 मिनट का पाठ

अनुरोध लूप का आरेख: 429 प्रतिक्रिया, बढ़ती देरी के साथ प्रतीक्षा चरण, और एक रीट्राई
इस पृष्ठ पर
  1. 429 का क्या अर्थ है
  2. देरी का अनुमान लगाने से पहले हेडर पढ़ें
  3. Python: jitter के साथ backoff
  4. JavaScript: वही लूप
  5. एजेंट को 429 कैसे संभालना चाहिए
  6. CheapTokens पर एजेंट लूप चलाएँ
  7. यदि फिर भी विफल हो

AI API से आने वाला 429 Too Many Requests का मतलब है कि अनुरोध अस्वीकार कर दिया गया क्योंकि आपने बहुत ज़्यादा बहुत तेज़ी से भेजा, या आपके खाते की सीमा पार हो गई। समाधान है रुककर exponential backoff और jitter के साथ फिर से प्रयास करना, जब प्रतिक्रिया में Retry-After हेडर हो तो उसका उपयोग करना, और यह सीमित करना कि आपका एजेंट समानांतर में कितने अनुरोध भेजता है। ऐसे 429 को फिर से प्रयास न करें जो वास्तव में खर्च या बैलेंस की सीमा है: रुकने से वह ठीक नहीं होगा।

यह गाइड OpenAI और Anthropic की आधिकारिक रेट-लिमिट गाइड पर आधारित है, दोनों 22 अक्टूबर 2026 को जाँची गईं। किसी भी पेज पर अंतिम-अद्यतन तिथि नहीं दिखती।

429 का क्या अर्थ है#

OpenAI 429 को रेट लिमिट पार होने के कारण अस्वीकार किए गए अनुरोध के रूप में बताता है (rate_limit_error, जब ट्रैफ़िक बहुत तेज़ी से बढ़ता है तो कोड slow_down के साथ), या क्योंकि कठोर खर्च सीमा पूरी हो गई। Anthropic भी 429 के लिए rate_limit_error का उपयोग करता है। खर्च-सीमा वाले 429 में retry-after हेडर नहीं होता और पहुँच बहाल होने तक विफल होता रहता है।

दो पड़ोसी स्थितियों को इससे भ्रमित करना आसान है। OpenAI का 503 server_is_overloaded और Anthropic का 529 overloaded_error ओवरलोड स्थितियाँ हैं, आपकी रेट लिमिट नहीं। इन्हें आमतौर पर उसी रीट्राई लूप से संभाला जाता है, लेकिन ये कारण के बारे में कुछ अलग कहते हैं।

तो तीन स्थितियाँ हैं, और हर एक के लिए अलग प्रतिक्रिया चाहिए:

प्रतिक्रिया कारण क्या करें
429 रेट लिमिट प्रति मिनट बहुत अधिक अनुरोध या टोकन रुकें, backoff के साथ फिर से प्रयास करें
429 खर्च या बैलेंस सीमा खाता सीमा पूरी हो गई फिर से प्रयास न करें; सीमा ठीक करें या बैलेंस टॉप अप करें
503 / 529 ओवरलोडेड प्रदाता पक्ष व्यस्त है सीमा के साथ, backoff के साथ फिर से प्रयास करें

यदि आपका बैलेंस खत्म हो गया है, तो इसके बजाय "not enough tokens" त्रुटि पढ़ें। टाइमआउट और अस्वीकृत कनेक्शन जैसी नेटवर्क-स्तरीय विफलताओं के लिए, सामान्य कनेक्शन त्रुटियाँ देखें।

देरी का अनुमान लगाने से पहले हेडर पढ़ें#

OpenAI रेट-सीमित प्रतिक्रियाओं पर ये हेडर दस्तावेज़ित करता है: Retry-After, और x-ratelimit-limit-requests, x-ratelimit-remaining-requests, x-ratelimit-reset-requests -tokens वेरिएंट के साथ। अन्य API इनमें से कुछ या कोई नहीं भेज सकते हैं, इसलिए क्लाइंट को ऐसे लिखें कि जब Retry-After मौजूद हो तो उसका उपयोग करे और जब न हो तो अपने स्वयं के शेड्यूल पर लौट आए।

OpenAI का रीट्राई पर मार्गदर्शन, संक्षेप में:

  • Retry-After को न्यूनतम प्रतीक्षा मानें और उसके ऊपर थोड़ी यादृच्छिक देरी जोड़ें।
  • इसके बिना, jitter के साथ exponential backoff का उपयोग करें।
  • प्रयासों की संख्या और कुल रीट्राई समय दोनों को सीमित करें।
  • SDK के रीट्राई के ऊपर अपने स्वयं के रीट्राई न जोड़ें।
  • कोटा या बिलिंग त्रुटियों पर फिर से प्रयास न करें।
  • विफल अनुरोध भी प्रति-मिनट सीमा में गिने जाते हैं, इसलिए आक्रामक लूप स्थिति को और खराब करता है।
  • स्ट्रीमिंग के लिए, किसी अनुरोध से आउटपुट पहले ही उपभोग कर लेने के बाद उसे दोबारा न चलाएँ।

Python: jitter के साथ backoff#

आधिकारिक openai पैकेज किसी भी OpenAI-संगत एंडपॉइंट के साथ काम करता है। SDK के अपने रीट्राई बंद करें (max_retries=0) ताकि वे आपके रीट्राई के साथ गुणा न हों। मॉडल की id CheapTokens दस्तावेज़ से आती है; id प्रदाताओं के बीच भिन्न होती हैं।

python
import os
import random
import time

from openai import OpenAI, APIStatusError

client = OpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
    max_retries=0,  # we retry ourselves
)

RETRYABLE = {429, 500, 502, 503, 504}


def chat_with_retry(model, messages, max_attempts=5, max_total=60.0):
    started = time.monotonic()
    for attempt in range(max_attempts):
        try:
            return client.chat.completions.create(model=model, messages=messages)
        except APIStatusError as err:
            last = attempt == max_attempts - 1
            if err.status_code not in RETRYABLE or last:
                raise
            header = err.response.headers.get("retry-after")
            if header and header.replace(".", "", 1).isdigit():
                delay = float(header) + random.uniform(0, 1)  # minimum wait + jitter
            else:
                delay = random.uniform(0, min(30.0, 2.0 ** attempt))  # full jitter
            if time.monotonic() - started + delay > max_total:
                raise
            time.sleep(delay)

हेडर के बिना देरी की ऊपरी सीमा 1, 2, 4, 8 सेकंड बढ़ती है (30 पर सीमित), और random.uniform उससे नीचे एक यादृच्छिक मान चुनता है, ताकि कई वर्कर एक ही समय पर न जागें। Retry-After HTTP तिथि भी हो सकता है; ऊपर का कोड संख्यात्मक रूप को संभालता है और अन्यथा backoff पर लौट आता है।

JavaScript: वही लूप#

javascript
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.cheaptokens.dev/v1",
  apiKey: process.env.CHEAPTOKENS_API_KEY,
  maxRetries: 0, // we retry ourselves
});

const RETRYABLE = new Set([429, 500, 502, 503, 504]);
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

export async function chatWithRetry(model, messages, maxAttempts = 5, maxTotalMs = 60000) {
  const started = Date.now();
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    try {
      return await client.chat.completions.create({ model, messages });
    } catch (err) {
      const last = attempt === maxAttempts - 1;
      if (!RETRYABLE.has(err.status) || last) throw err;
      const header = Number(err.headers?.get?.("retry-after"));
      const delayMs = Number.isFinite(header) && header > 0
        ? header * 1000 + Math.random() * 1000 // minimum wait + jitter
        : Math.random() * Math.min(30000, 2 ** attempt * 1000); // full jitter
      if (Date.now() - started + delayMs > maxTotalMs) throw err;
      await sleep(delayMs);
    }
  }
}

जब यह काम करता है, तो रेट-सीमित कॉल बस अधिक समय लेती है और फिर सामान्य पूर्णता लौटाती है। जब अंतिम प्रयास के बाद भी यह विफल रहता है, तो मूल त्रुटि उठाई जाती है, ताकि आपका कोड उसे लॉग कर सके या कार्य को बाद के लिए कतार में डाल सके।

एजेंट को 429 कैसे संभालना चाहिए#

एक एजेंट लूप कई छोटी कॉल भेजता है, और कई एजेंट या टूल कॉल एक साथ चल सकते हैं। केवल फिर से प्रयास करना पर्याप्त नहीं है; स्रोत पर अनुरोध दर कम करें:

  1. समवर्तीता सीमित करें। 3–5 समानांतर कॉल का सेमाफोर उचित शुरुआत है; इसे केवल तब बढ़ाएँ जब त्रुटियाँ दुर्लभ रहें।
  2. एक लिमिटर साझा करें। यदि कई वर्कर एक ही कुंजी का उपयोग करते हैं, तो वे वही सीमाएँ साझा करते हैं, इसलिए प्रति वर्कर एक रीट्राई लूप पर्याप्त नहीं है: प्रक्रिया के लिए एक कतार या एक सेमाफोर का उपयोग करें।
  3. वैश्विक रूप से back off करें। जब एक कॉल को देरी के साथ 429 मिलता है, तो केवल विफल कॉल को नहीं, पूरे पूल को उस समय के लिए रोकें।
  4. अनुरोध छोटे रखें। प्रति अनुरोध कम टोकन का मतलब है प्रति-मिनट टोकन सीमाओं पर कम दबाव: इतिहास और टूल आउटपुट छोटा करें। टोकन कहाँ जाते हैं, इसके लिए AI एजेंट की लागत का अनुमान कैसे लगाएँ देखें।
  5. गैर-रीट्राई-योग्य त्रुटियों पर रुकें। 401, 400, या बैलेंस त्रुटि स्वयं ठीक नहीं होगी; तेज़ी से विफल हों और रिपोर्ट करें।
python
import asyncio

limit = asyncio.Semaphore(4)  # at most 4 requests in flight


async def run(job):
    async with limit:
        return await call_model(job)  # your async call with the retry loop above

CheapTokens पर एजेंट लूप चलाएँ#

कई छोटी कॉल वाले एजेंट लूप के लिए, CheapTokens MiniMax-M2.7 प्रदान करता है: दिन के किसी भी समय एक ही मूल्य, 180K कॉन्टेक्स्ट, प्रति उत्तर अधिकतम 8,192 टोकन, और सभी मॉडलों के लिए एक बैलेंस। आउटपुट का मूल्य $0.15 प्रति 1M टोकन है, और कुल मिलाकर, इनपुट और आउटपुट को एक साथ गिनते हुए, यह OpenRouter से सस्ता है। यह OpenAI-संगत एंडपॉइंट https://api.cheaptokens.dev/v1 के माध्यम से काम करता है। ऊपर का कोड पहले से इसी एंडपॉइंट की ओर इंगित करता है; CheapTokens दस्तावेज़ से मॉडल id सेट करें और इसे चलाएँ।

500,000-इनपुट, 100,000-आउटपुट वर्कलोड के लिए लाइव मूल्य:

मॉडल लागत OpenRouter
GLM-5.3-Flash $0.014 $0.0282
DeepSeek-V4-Flash $0.0175 $0.0394
MiniMax-M2.7 $0.04 $0.27

कुल 5,00,000 इनपुट और 1,00,000 आउटपुट टोकन। प्रति 1M टोकन की कीमतें वर्तमान हैं और हमारे टैरिफ के साथ बदलती रहती हैं; OpenRouter कॉलम समान कार्यभार के लिए संदर्भ कीमतें दिखाता है।

सभी मूल्य, सेटअप दस्तावेज़ देखें, और अपना पहला अनुरोध भेजने के लिए एक कुंजी बनाएँ।

यदि फिर भी विफल हो#

  • पहले ही अनुरोध पर 429। प्रतिक्रिया बॉडी में त्रुटि प्रकार और संदेश पढ़ें: खर्च या खाता-सीमा वाला 429 सीमा बढ़ाए जाने या पहुँच बहाल होने तक रीट्राई पर विफल होता रहता है, जबकि रेट-लिमिट वाला 429 विराम के बाद साफ हो जाता है।
  • लंबे लूप के साथ 429 आता रहता है। आप रीट्राई को परतों में जोड़ रहे होंगे: SDK रीट्राई गुणा आपके रीट्राई। उदाहरणों की तरह SDK को शून्य पर सेट करें।
  • बैच की शुरुआत में त्रुटियाँ झुंड में आती हैं। सभी वर्कर एक साथ न चलाएँ, धीरे-धीरे बढ़ाएँ; OpenAI बहुत तेज़ी से बढ़ते ट्रैफ़िक के लिए slow_down की रिपोर्ट करता है।
  • स्ट्रीमिंग कॉल बीच में विफल हुई। आउटपुट उपभोग करने के बाद उसे बिना सोचे दोबारा न चलाएँ; तय करें कि पूरा उत्तर फिर से शुरू करना है या जो है उसी से जारी रखना है।
  • प्रतिक्रिया में Retry-After नहीं है। कोड jitter के साथ backoff पर लौट आता है, इसलिए कोई बदलाव आवश्यक नहीं है।