এরর হ্যান্ডলিং
ব্যর্থ রিকোয়েস্ট একটি HTTP স্ট্যাটাস কোড এবং এররের ধরন ও বার্তাসহ একটি JSON বডি ফেরত দেয়। এই পেজে প্রতিটি স্ট্যাটাসের তালিকা, প্রতিটি API ফরম্যাটের এরর বডি এবং কোন এরর আবার পাঠানোর যোগ্য তা দেওয়া আছে।
SDK একটি এরর অবজেক্ট তোলে, যাতে স্ট্যাটাস কোড ও বডির ফিল্ডগুলো থাকে। এই রিকোয়েস্ট এমন একটি মডেলের নাম দিয়েছে যা নেই:
import openai
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.shannon-ai.com/v1",
)
try:
client.chat.completions.create(
model="no-such-model",
messages=[{"role": "user", "content": "Hello"}],
)
except openai.APIStatusError as error:
print(error.status_code) # 400
print(error.type) # invalid_request_error
print(error.body["message"]) # unknown model: no-such-model
print(error.response.headers.get("x-request-id")) # the id of this request import OpenAI from "openai";
const client = new OpenAI({
apiKey: "YOUR_API_KEY",
baseURL: "https://api.shannon-ai.com/v1",
});
try {
await client.chat.completions.create({
model: "no-such-model",
messages: [{ role: "user", content: "Hello" }],
});
} catch (error) {
if (!(error instanceof OpenAI.APIError)) throw error;
console.log(error.status); // 400
console.log(error.type); // invalid_request_error
console.log(error.error.message); // unknown model: no-such-model
} curl -i https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "no-such-model",
"messages": [{"role": "user", "content": "Hello"}]
}' এটি স্ট্যাটাস 400 এবং এই বডি ফেরত দেয়:
{
"error": {
"type": "invalid_request_error",
"message": "unknown model: no-such-model"
}
} এরর বডি
বডি দুই ধরনের। /v1/messages Anthropic ফরম্যাটে উত্তর দেয়; বাকি সব এন্ডপয়েন্ট OpenAI ফরম্যাটে। দুটোতেই বিবরণ থাকে error.type ও error.message-এ, তাই একটি রিডারই সব এন্ডপয়েন্টের জন্য যথেষ্ট।
{
"error": {
"type": "authentication_error",
"message": "Invalid API key",
"code": "invalid_api_key",
"param": null
}
} {
"type": "error",
"error": {
"type": "authentication_error",
"message": "Invalid API key"
}
} | ফিল্ড | টাইপ | বিবরণ |
|---|---|---|
error.type | string | এররের ধরন। নিচে এররের ধরন দেখুন। |
error.message | string | মানুষের জন্য একটি বাক্য। নিচের টেবিলের টেক্সটগুলো স্থির, শুধু পরিবর্তনশীল অংশ বাদে, যা <id>, <n> বা … হিসেবে দেখানো। |
error.code | string | null | OpenAI ফরম্যাটের কিছু এররে থাকে: 401-এর সাথে invalid_api_key, 413-এর সাথে request_too_large, কথোপকথন বেশি দীর্ঘ হলে context_length_exceeded, অন্যথায় null বা অনুপস্থিত। আগে স্ট্যাটাস ও error.type দেখে সিদ্ধান্ত নিন, code-কে বাড়তি তথ্য হিসেবে ধরুন। |
error.param | null | code-এর মতো একই এররগুলোতে থাকে। সবসময় null। |
type | string | শুধু Anthropic ফরম্যাটে। সবসময় error। |
এররের ধরন
| টাইপ | স্ট্যাটাস | বিবরণ |
|---|---|---|
invalid_request_error | 400, 413, 415, 422 | রিকোয়েস্টটিই ভুল: কোনো ফিল্ড, বডি, মডেল id, বা মডেল নেয় না এমন ইনপুট। আবার পাঠানোর আগে রিকোয়েস্ট বদলান। |
authentication_error | 401 | API key নেই, অজানা, বা বাতিল করা হয়েছে। |
not_found_error | 404 | পাথটি নেই। |
rate_limit_error | 429 | ব্যালেন্স রিকোয়েস্টের খরচ মেটায় না, ফ্লাড প্রোটেকশন থামিয়েছে, অথবা মডেল ব্যস্ত। বার্তায় বলা থাকে কোনটি। |
api_error | 500, 502, 503, 504 | রিকোয়েস্ট ঠিক ছিল, ব্যর্থতা আমাদের দিকে। আবার পাঠান। |
server_error | 500 | রিকোয়েস্ট ঠিক ছিল, ব্যর্থতা আমাদের দিকে। আবার পাঠান। |
স্ট্যাটাস কোড
| স্ট্যাটাস | টাইপ | বার্তা | কখন |
|---|---|---|---|
400 | invalid_request_error | Failed to parse the request body as JSON: … | বডি বৈধ JSON নয়। |
400 | invalid_request_error | unknown model: <id> | model কোনো প্রকাশিত id নয়। /v1/responses-এ model না থাকলেও এটি হয়। |
400 | invalid_request_error | No user message provided | Shannon টিয়ার: রিকোয়েস্টে ব্যবহারকারীর কোনো টেক্সট নেই। |
400 | invalid_request_error | <id> does not accept image input | ইমেজ ইনপুট নেই এমন একটি হোস্টেড ওপেন-ওয়েট মডেলকে ইমেজ পাঠানো হয়েছে। |
400 | invalid_request_error | audio and video input are not supported by any hosted model | একটি হোস্টেড ওপেন-ওয়েট মডেলকে অডিও বা ভিডিও অংশ পাঠানো হয়েছে। |
400 | invalid_request_error | <id> does not accept response_format | স্ট্রাকচার্ড আউটপুট নেই এমন একটি হোস্টেড ওপেন-ওয়েট মডেলের কাছে তা চাওয়া হয়েছে। |
400 | invalid_request_error | <id> does not accept response_format json_schema; use json_object | শুধু json_object নেয় এমন একটি হোস্টেড ওপেন-ওয়েট মডেলকে JSON schema পাঠানো হয়েছে। |
400 | invalid_request_error | unknown reasoning effort '<value>'; expected off, low, medium or high | রিজনিং এফোর্ট তালিকার মানগুলোর কোনোটি নয়। হোস্টেড ওপেন-ওয়েট মডেল। |
400 | invalid_request_error | count_tokens is available for the hosted open models; unknown model: <id> | হোস্টেড ওপেন-ওয়েট মডেলের বাইরের কোনো মডেলের জন্য token গণনা চাওয়া হয়েছে। |
401 | authentication_error | Missing authentication | কোনো API key পাঠানো হয়নি। |
401 | authentication_error | Invalid API key | key অজানা, নতুনটি দিয়ে বদলে গেছে, অথবা বাতিল করা হয়েছে। |
404 | not_found_error | Not Found | পাথটি নেই, যেমন /v1/embeddings। |
405 | api_error | Method Not Allowed | পাথটি আছে, কিন্তু এই HTTP মেথডে নেই। |
413 | invalid_request_error | Failed to buffer the request body: … | রিকোয়েস্ট বডি 32 MiB-এর চেয়ে বড়। |
415 | invalid_request_error | Expected request with `Content-Type: application/json` | Content-Type হেডার নেই অথবা application/json নয়। |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | messages-এর মতো একটি আবশ্যক ফিল্ড নেই, অথবা কোনো ফিল্ডের JSON type ভুল। |
429 | rate_limit_error | Quota exceeded. Upgrade your plan at shannon-ai.com/plan | রিকোয়েস্টের আউটপুট সীমা আপনার অবশিষ্ট ব্যালেন্সের চেয়ে বড়। |
429 | rate_limit_error | Too many requests. Retry in <n>s. | ফ্লাড প্রোটেকশন: আপনার অ্যাকাউন্টে এক মিনিটে 120টির বেশি রিকোয়েস্ট। <n> হলো মিনিট শেষ হতে বাকি সেকেন্ড। |
429 | rate_limit_error | Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan | /v1/chat/completions ও /v1/messages-এ shannon-coder-1: বর্তমান 4 ঘণ্টার উইন্ডোর জন্য আপনার প্ল্যানের Shannon Coder কল শেষ। |
429 | rate_limit_error | Shannon routes are temporarily busy. Please retry. | মডেলটি এই মুহূর্তে ব্যস্ত। |
500 | server_error | The model backend failed to answer. Please retry. | মডেল কোনো উত্তর তৈরি করেনি। |
500 | server_error | An internal error occurred. Please retry. | রিকোয়েস্ট প্রস্তুত করার সময় অভ্যন্তরীণ ব্যর্থতা। |
502 | api_error | The model backend failed to answer. Please retry. | মডেল কোনো উত্তর তৈরি করেনি। Shannon 3 পরিবার ও হোস্টেড ওপেন-ওয়েট মডেল। |
503 | api_error | Could not verify your quota right now. Please retry. | এই মুহূর্তে আপনার ব্যালেন্স পড়া যায়নি। |
503 | api_error | token counting is temporarily unavailable for this model | এই মুহূর্তে এই মডেলের জন্য token গণনা পাওয়া যাচ্ছে না। |
504 | api_error | upstream timed out | স্ট্রিম না করা রিকোয়েস্টের সময়সীমার চেয়ে বেশি সময় নিয়েছে একটি হোস্টেড ওপেন-ওয়েট মডেল। |
যাচাই এই ক্রমে চলে: API key, রিকোয়েস্ট বডি, মডেল id, ফ্লাড প্রোটেকশন, ব্যালেন্স। তাই ভুল key ও ভুল বডিসহ রিকোয়েস্ট 401 ফেরত দেয়। 4xx স্ট্যাটাসে প্রত্যাখ্যাত রিকোয়েস্টে চার্জ হয় না।
ব্যালেন্স ও ফ্লাড প্রোটেকশন
প্রতিটি রিকোয়েস্ট সমানভাবে সরবরাহ করা হয়: কোনো রেট টিয়ার নেই এবং আলাদা API কোটা নেই। তবু দুটি কারণে 429 আসতে পারে, দুটোতেই type rate_limit_error। বার্তা দেখে আলাদা করা যায়।
ব্যালেন্স
আপনার ব্যালেন্স হলো আজকের প্ল্যান এলাউন্স, যা 00:00 UTC-তে রিসেট হয়, এবং তারপর আপনার কেনা ক্রেডিট। চ্যাট ও API একই ব্যালেন্স থেকে খরচ করে।
প্রতিটি রিকোয়েস্ট প্রথমে নিজের আউটপুট সীমা আলাদা করে রাখে: max_tokens, অথবা /v1/responses-এ max_output_tokens, কোনোটিই না দিলে 4,096। উত্তর সম্পূর্ণ হলে আলাদা করা পরিমাণ রিকোয়েস্টের প্রকৃত ব্যবহারে বদলে যায়। পরিমাণটি অবশিষ্ট ব্যালেন্সে না ধরলে মডেল শুরু হওয়ার আগেই রিকোয়েস্ট Quota exceeded ফেরত দেয়।
একই সময়ে চলা রিকোয়েস্টগুলো প্রত্যেকে নিজের পরিমাণ আলাদা করে রাখে। তাই বড় max_tokens সহ অনেক সমান্তরাল রিকোয়েস্ট প্রতিটি উত্তর ছোট হলেও কিছুক্ষণের জন্য ব্যালেন্স ফুরিয়ে দিতে পারে। ছোট max_tokens কম আলাদা করে রাখে।
ফ্লাড প্রোটেকশন
ফ্লাড প্রোটেকশনে প্রতি অ্যাকাউন্টে প্রতি মিনিটে 120টি রিকোয়েস্ট চলে। এটি key নয়, অ্যাকাউন্ট ধরে গোনে, এবং /v1/chat/completions, /v1/responses ও /v1/messages একসাথে ধরে। মিনিট শুরু হয় আপনার প্রথম রিকোয়েস্ট থেকে।
ওই মিনিটের মধ্যে 121 নম্বর রিকোয়েস্ট Too many requests. Retry in <n>s. ফেরত দেয় এবং কোনো খরচ হয় না। প্রত্যাখ্যাত রিকোয়েস্টও গণনায় ধরা হয়, তাই অপেক্ষা না করে আবার পাঠানো ক্লায়েন্ট মিনিট শেষ না হওয়া পর্যন্ত প্রত্যাখ্যাত হতে থাকে। বার্তায় দেওয়া <n> সেকেন্ড অপেক্ষা করুন।
সমান্তরালে পাঠানো রিকোয়েস্ট সমান্তরাল বলে প্রত্যাখ্যাত হয় না। সেগুলো সারিতে অপেক্ষা করে এবং পালাক্রমে উত্তর পায়।
GET /v1/models এবং token গণনার এন্ডপয়েন্টগুলো গণনায় ধরা হয় না।
লিমিট ও ব্যালেন্স সম্পর্কে আরও, এবং নিজের ব্যালেন্স ও ব্যবহার কোথায় দেখবেন: সীমা ও ব্যালেন্স Keys & usage
কোনগুলো আবার চেষ্টা করবেন
একই রিকোয়েস্ট সফল হতে পারলেই কেবল আবার পাঠান। OpenAI ও Anthropic SDK নিজে থেকেই 429 ও 5xx উত্তরে দুবার পুনরায় চেষ্টা করে; তা বদলাতে max_retries (JavaScript-এ maxRetries) সেট করুন।
| এরর | আবার পাঠাবেন? | কীভাবে |
|---|---|---|
400, 404, 405, 413, 415, 422 | না। আগে রিকোয়েস্ট ঠিক করুন। | বার্তায় ভুল ফিল্ড, মডেল বা ইনপুটের নাম থাকে। |
401 | না। বৈধ key ব্যবহার করুন। | Keys & usage পেজে key তৈরি করুন বা বদলান। |
429 Too many requests | হ্যাঁ, অপেক্ষার পর। | বার্তায় দেওয়া সেকেন্ড সংখ্যা অপেক্ষা করুন, তারপর একই রিকোয়েস্ট পাঠান। |
429 Quota exceeded | যেমন আছে তেমন নয়। | max_tokens কমান, 00:00 UTC-তে দৈনিক রিসেটের জন্য অপেক্ষা করুন, অথবা ক্রেডিট যোগ করুন। |
429 Shannon Coder call quota reached | হ্যাঁ, পরবর্তী উইন্ডোতে। | উইন্ডো 00:00 UTC থেকে প্রতি 4 ঘণ্টায় শুরু হয়। অন্য মডেল সাথে সাথে উত্তর দেয়। |
429 … temporarily busy | হ্যাঁ। | কয়েক সেকেন্ড অপেক্ষা করুন, প্রতিবার আরও বেশি সময় অপেক্ষা করুন। |
500, 502, 503 | হ্যাঁ। | 1 সেকেন্ড অপেক্ষা করুন, তারপর 2, 4 ও 8। কয়েকবার চেষ্টার পর থামুন এবং রিকোয়েস্ট id জানান। |
504 | হ্যাঁ। | stream কে true করে পাঠান: সময়সীমা শুধু স্ট্রিম না করা উত্তরের ক্ষেত্রে প্রযোজ্য। |
এই টেবিল মেনে চলা একটি রিট্রাই লুপ:
import re
import time
import openai
from openai import OpenAI
# max_retries=0: this loop does the retrying, the SDK does not add its own.
client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1", max_retries=0)
def create_with_retry(attempts=5, **request):
for attempt in range(attempts):
try:
return client.chat.completions.create(**request)
except openai.RateLimitError as error:
text = str(error)
flood = re.search(r"Retry in (\d+)s", text)
if flood:
time.sleep(int(flood.group(1))) # flood protection: wait out the minute
elif "temporarily busy" in text:
time.sleep(2 ** attempt)
else:
raise # balance: a wait of seconds does not help
except (openai.InternalServerError, openai.APIConnectionError):
time.sleep(2 ** attempt) # 1, 2, 4, 8 seconds
raise RuntimeError("the request failed after all attempts")
response = create_with_retry(
model="shannon-3",
messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content) import OpenAI from "openai";
// maxRetries: 0 — this loop does the retrying, the SDK does not add its own.
const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.shannon-ai.com/v1", maxRetries: 0 });
const sleep = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));
async function createWithRetry(request, attempts = 5) {
for (let attempt = 0; attempt < attempts; attempt++) {
try {
return await client.chat.completions.create(request);
} catch (error) {
const text = String(error.message);
const flood = text.match(/Retry in (\d+)s/);
if (error.status === 429 && flood) {
await sleep(Number(flood[1])); // flood protection: wait out the minute
} else if (error.status === 429 && text.includes("temporarily busy")) {
await sleep(2 ** attempt);
} else if (error.status >= 500 || error instanceof OpenAI.APIConnectionError) {
await sleep(2 ** attempt); // 1, 2, 4, 8 seconds
} else {
throw error; // wrong request, wrong key or balance
}
}
}
throw new Error("the request failed after all attempts");
}
const response = await createWithRetry({
model: "shannon-3",
messages: [{ role: "user", content: "Hello" }],
});
console.log(response.choices[0].message.content); স্ট্রিমের ভেতরের এরর
স্ট্রিমের স্ট্যাটাস প্রথম বাইট থেকেই 200। এরপর কোনো ব্যর্থতা এলে তা স্ট্রিমের ভেতরে ইভেন্ট হিসেবে আসে: /v1/chat/completions-এ error সদস্যসহ একটি চাঙ্ক, /v1/messages-এ একটি error ইভেন্ট, /v1/responses-এ একটি response.failed বা error ইভেন্ট। স্ট্রিমের সমাপ্তি ইভেন্টগুলো তারপরও আসে। এমন উত্তরকে ব্যর্থ ধরুন এবং 5xx স্ট্যাটাসের মতো রিকোয়েস্ট আবার পাঠান।
মডেলের কনটেক্সট উইন্ডোর চেয়ে দীর্ঘ কথোপকথন এভাবে জানানো হয়, type invalid_request_error ও code context_length_exceeded সহ। আবার পাঠানোর আগে কথোপকথন ছোট করুন।
সঠিক ফ্রেমগুলো স্ট্রিমিং পেজে বর্ণিত আছে। স্ট্রিমিং
রিকোয়েস্ট id
প্রতিটি উত্তরে, এররসহ, একটি x-request-id হেডার থাকে। এটি আপনার নিজের পাঠানো x-request-id হেডারের মান, না পাঠালে 12টি হেক্সাডেসিমাল অক্ষর। এটি লগ করুন, এবং কোনো রিকোয়েস্ট নিয়ে সাহায্য চাইলে উল্লেখ করুন।