การจัดการข้อผิดพลาด
คำขอที่ล้มเหลวจะคืนรหัสสถานะ HTTP และ body แบบ JSON ที่มีประเภทข้อผิดพลาดและข้อความ หน้านี้แสดงรายการทุกสถานะ แสดง error body ของ API แต่ละรูปแบบ และบอกว่าข้อผิดพลาดใดควรส่งซ้ำ
SDK จะโยนออบเจกต์ข้อผิดพลาดที่มีรหัสสถานะและฟิลด์ของ body คำขอนี้ระบุโมเดลที่ไม่มีอยู่:
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 และ body นี้:
{
"error": {
"type": "invalid_request_error",
"message": "unknown model: no-such-model"
}
} เนื้อหาข้อผิดพลาด
มี body สองแบบ /v1/messages ตอบในรูปแบบ Anthropic ส่วน endpoint อื่นทั้งหมดตอบในรูปแบบ OpenAI ทั้งสองแบบมีรายละเอียดอยู่ใน error.type และ error.message ตัวอ่านเดียวจึงใช้ได้กับทุก endpoint
{
"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: invalid_api_key กับ 401, request_too_large กับ 413, context_length_exceeded เมื่อบทสนทนายาวเกินไป นอกนั้นเป็น null หรือไม่มี ให้ตัดสินจากสถานะและ error.type ก่อน และถือว่า code เป็นข้อมูลเสริม |
error.param | null | มีในข้อผิดพลาดชุดเดียวกับ code เป็น null เสมอ |
type | string | เฉพาะรูปแบบ Anthropic เป็น error เสมอ |
ประเภทข้อผิดพลาด
| ประเภท | สถานะ | คำอธิบาย |
|---|---|---|
invalid_request_error | 400, 413, 415, 422 | คำขอเองผิด: ฟิลด์ body model id หรืออินพุตที่โมเดลไม่รับ แก้คำขอก่อนส่งอีกครั้ง |
authentication_error | 401 | API key หายไป ไม่รู้จัก หรือถูกเพิกถอน |
not_found_error | 404 | ไม่มีเส้นทางนี้ |
rate_limit_error | 429 | ยอดคงเหลือไม่พอสำหรับคำขอ flood protection หยุดไว้ หรือโมเดลไม่ว่าง ข้อความจะบอกว่าเป็นกรณีใด |
api_error | 500, 502, 503, 504 | คำขอไม่มีปัญหา ความล้มเหลวอยู่ที่ฝั่งเรา ส่งใหม่อีกครั้ง |
server_error | 500 | คำขอไม่มีปัญหา ความล้มเหลวอยู่ที่ฝั่งเรา ส่งใหม่อีกครั้ง |
รหัสสถานะ
| สถานะ | ประเภท | ข้อความ | เมื่อไร |
|---|---|---|---|
400 | invalid_request_error | Failed to parse the request body as JSON: … | body ไม่ใช่ 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 | ส่งรูปภาพไปยังโมเดล open-weight ที่โฮสต์ซึ่งไม่รองรับอินพุตรูปภาพ |
400 | invalid_request_error | audio and video input are not supported by any hosted model | ส่งส่วนเสียงหรือวิดีโอไปยังโมเดล open-weight ที่โฮสต์ |
400 | invalid_request_error | <id> does not accept response_format | ขอเอาต์พุตแบบมีโครงสร้างจากโมเดล open-weight ที่โฮสต์ซึ่งไม่รองรับ |
400 | invalid_request_error | <id> does not accept response_format json_schema; use json_object | ส่ง JSON schema ไปยังโมเดล open-weight ที่โฮสต์ซึ่งรับเฉพาะ json_object |
400 | invalid_request_error | unknown reasoning effort '<value>'; expected off, low, medium or high | ระดับความพยายามในการให้เหตุผลไม่ใช่ค่าใดค่าหนึ่งในรายการ โมเดล open-weight ที่โฮสต์ |
400 | invalid_request_error | count_tokens is available for the hosted open models; unknown model: <id> | ขอนับ tokens สำหรับโมเดลที่อยู่นอกโมเดล open-weight ที่โฮสต์ |
401 | authentication_error | Missing authentication | ไม่ได้ส่ง API key |
401 | authentication_error | Invalid API 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: … | เนื้อหาคำขอ (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 ไม่ถูกต้อง |
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. | Flood protection: มีคำขอมากกว่า 120 รายการในหนึ่งนาทีบนบัญชีของคุณ <n> คือจำนวนวินาทีจนกว่านาทีนั้นจะสิ้นสุด |
429 | rate_limit_error | Shannon Coder call quota reached. Upgrade your plan at shannon-ai.com/plan | shannon-coder-1 บน /v1/chat/completions และ /v1/messages: ใช้การเรียก Shannon Coder ตามแผนของคุณครบแล้วสำหรับช่วง 4 ชั่วโมงปัจจุบัน |
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 และโมเดล open-weight ที่โฮสต์ |
503 | api_error | Could not verify your quota right now. Please retry. | ไม่สามารถอ่านยอดคงเหลือของคุณได้ในขณะนี้ |
503 | api_error | token counting is temporarily unavailable for this model | การนับ tokens ใช้ไม่ได้สำหรับโมเดลนี้ในขณะนี้ |
504 | api_error | upstream timed out | โมเดล open-weight ที่โฮสต์ใช้เวลานานเกินกว่าเวลาจำกัดของคำขอที่ไม่ใช่สตรีม |
การตรวจสอบทำตามลำดับนี้: API key, body ของคำขอ, model id, flood protection, ยอดคงเหลือ ดังนั้นคำขอที่มีทั้งคีย์ผิดและ body ผิดจะได้รับ 401 คำขอที่ถูกปฏิเสธด้วยสถานะ 4xx จะไม่ถูกเรียกเก็บเงิน
ยอดคงเหลือและ flood protection
ทุกคำขอได้รับบริการเท่าเทียมกัน: ไม่มีระดับอัตราและไม่มีโควตา API แยกต่างหาก แต่ยังมีสองกรณีที่ตอบ 429 ได้ ทั้งสองมีประเภท rate_limit_error ข้อความจะบอกว่าเป็นกรณีใด
ยอดคงเหลือ
ยอดคงเหลือของคุณคือโควตาแผนของวันนี้ ซึ่งรีเซ็ตที่ 00:00 UTC และถัดจากนั้นคือเครดิตที่ซื้อ แชตและ API หักจากยอดคงเหลือเดียวกัน
แต่ละคำขอจะกันขีดจำกัดเอาต์พุตของตัวเองไว้ก่อน: max_tokens หรือ max_output_tokens บน /v1/responses ซึ่งเป็น 4,096 เมื่อคุณไม่ได้ส่งทั้งสอง เมื่อคำตอบสมบูรณ์ ยอดที่กันไว้จะถูกแทนที่ด้วยจำนวนที่คำขอใช้จริง หากยอดนั้นไม่พอในยอดคงเหลือที่เหลืออยู่ คำขอจะคืน Quota exceeded ก่อนที่โมเดลจะเริ่ม
คำขอที่ทำงานพร้อมกันแต่ละรายการกันยอดของตัวเอง ดังนั้นคำขอขนานจำนวนมากที่มี max_tokens สูงอาจทำให้ยอดคงเหลือถูกกันไว้จนหมดชั่วคราว แม้ว่าแต่ละคำตอบจะสั้นก็ตาม max_tokens ที่ต่ำลงจะกันไว้น้อยลง
Flood protection
Flood protection อนุญาต 120 คำขอต่อนาทีต่อบัญชี นับตามบัญชี ไม่ใช่ตามคีย์ รวม /v1/chat/completions, /v1/responses และ /v1/messages เข้าด้วยกัน นาทีเริ่มนับจากคำขอแรกของคุณ
คำขอลำดับที่ 121 ภายในนาทีนั้นจะคืน Too many requests. Retry in <n>s. และไม่มีค่าใช้จ่าย คำขอที่ถูกปฏิเสธก็นับด้วย ดังนั้นไคลเอนต์ที่ส่งซ้ำโดยไม่รอจะยังถูกปฏิเสธจนกว่านาทีนั้นจะสิ้นสุด ให้รอ <n> วินาทีตามข้อความ
คำขอที่ส่งแบบขนานจะไม่ถูกปฏิเสธเพียงเพราะเป็นแบบขนาน แต่จะรอในคิวและได้รับคำตอบตามลำดับ
GET /v1/models และ endpoint นับ tokens ไม่ถูกนับ
ข้อมูลเพิ่มเติมเกี่ยวกับข้อจำกัดและยอดคงเหลือ และที่ที่จะดูยอดคงเหลือและการใช้งานของคุณเอง: ขีดจำกัดและยอดคงเหลือ คีย์และการใช้งาน
สิ่งที่ควรลองใหม่
ส่งคำขอซ้ำเฉพาะเมื่อคำขอเดิมมีโอกาสสำเร็จ OpenAI และ Anthropic SDK ลองซ้ำคำตอบ 429 และ 5xx สองครั้งด้วยตัวเองอยู่แล้ว ตั้งค่า max_retries (maxRetries ใน JavaScript) เพื่อเปลี่ยนจำนวนครั้ง
| ข้อผิดพลาด | ส่งซ้ำได้หรือไม่ | วิธีการ |
|---|---|---|
400, 404, 405, 413, 415, 422 | ไม่ได้ แก้คำขอก่อน | ข้อความจะระบุฟิลด์ โมเดล หรืออินพุตที่ผิด |
401 | ไม่ได้ ใช้คีย์ที่ถูกต้อง | สร้างหรือเปลี่ยนคีย์ในหน้าคีย์และการใช้งาน |
429 Too many requests | ได้ หลังจากรอ | รอตามจำนวนวินาทีในข้อความ แล้วส่งคำขอเดิม |
429 Quota exceeded | ไม่ใช่ตามที่เป็น | ลด max_tokens รอการรีเซ็ตรายวันที่ 00:00 UTC หรือเติมเครดิต |
429 Shannon Coder call quota reached | ได้ ในช่วงเวลาถัดไป | ช่วงเวลาเริ่มทุก 4 ชั่วโมงตั้งแต่ 00:00 UTC โมเดลอื่นตอบได้ทันที |
429 … temporarily busy | ได้ | รอสักสองสามวินาที แล้วรอนานขึ้นในแต่ละครั้งที่ลองต่อไป |
500, 502, 503 | ได้ | รอ 1 วินาที แล้ว 2, 4 และ 8 หยุดหลังลองไม่กี่ครั้งและรายงาน request 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 ตั้งแต่ไบต์แรก ความล้มเหลวหลังจากนั้นจะมาถึงเป็นอีเวนต์ภายในสตรีม: chunk ที่มีสมาชิก error บน /v1/chat/completions, อีเวนต์ error บน /v1/messages, อีเวนต์ response.failed หรือ error บน /v1/responses อีเวนต์ปิดท้ายของสตรีมยังคงตามมา ให้ถือว่าคำตอบนั้นล้มเหลวและส่งคำขอใหม่ เช่นเดียวกับสถานะ 5xx
บทสนทนาที่ยาวกว่า context window ของโมเดลจะถูกรายงานด้วยวิธีนี้ โดยมีประเภท invalid_request_error และรหัส context_length_exceeded ให้ทำให้บทสนทนาสั้นลงก่อนส่งอีกครั้ง
เฟรมที่แน่นอนอธิบายไว้ในหัวข้อ streaming สตรีมมิง
Request id
ทุกคำตอบ รวมถึงข้อผิดพลาด มีเฮดเดอร์ x-request-id ซึ่งเป็นค่าที่คุณส่งในเฮดเดอร์ x-request-id ของคุณเอง หรืออักขระเลขฐานสิบหก 12 ตัวเมื่อคุณไม่ได้ส่ง ให้บันทึกค่านี้ไว้ และอ้างอิงเมื่อขอความช่วยเหลือเกี่ยวกับคำขอ