รูปแบบของ Error — problem+json
status code บอก ประเภทไหน ของ error; ส่วน body ควรบอกว่า อะไรเฉพาะเจาะจง ที่ผิดพลาด ในรูปทรงที่เหมือนกันทุก endpoint การคิดค้นรูปทรง error ใหม่ในแต่ละ endpoint คือภาษีที่ client ต้องจ่ายไปตลอด
RFC 9457 Problem Details
หัวข้อที่มีชื่อว่า “RFC 9457 Problem Details”เรื่องนี้มีมาตรฐานรองรับอยู่แล้ว คือ Problem Details for HTTP APIs (RFC 9457) ที่ส่งออกมาเป็น application/problem+json โดยมีสมาชิกดังนี้:
type— URI ที่ระบุประเภทของปัญหา (key ที่เสถียรและจัดทำเอกสารได้)title— สรุปสั้นๆ ที่คนอ่านเข้าใจ (เสถียรตามtypeแต่ละตัว)status— HTTP status code ที่ระบุซ้ำใน bodydetail— คำอธิบายที่คนอ่านเข้าใจ เจาะจงเฉพาะกรณีนี้instance— URI สำหรับกรณีนี้โดยเฉพาะ (มักเป็น path ของ request)- รวมถึง extension member ใดๆ ที่คุณต้องการ (เช่น array
errors)
{ "type": "https://api.example.com/problems/out-of-stock", "title": "Item is out of stock", "status": 409, "detail": "Only 2 units of SKU-123 remain; you requested 5.", "instance": "/orders/8821", "available": 2}การสร้าง problem object ใน code
หัวข้อที่มีชื่อว่า “การสร้าง problem object ใน code”| ข้อดี (Standard Error Format) | ข้อแลกเปลี่ยน |
|---|---|
| client จัดการ error แบบ programmatic ได้ | ต้องออกแบบ error schema และยึดตลอด API |
| machine-readable error code ช่วย retry logic | error detail มากเกิน → อาจ expose internal info |
type URI ใน Problem JSON ชี้ไป documentation | verbose กว่า { "error": "..." } แบบง่าย |
| stack trace ใน error ช่วย debug ใน development | stack trace ใน production เป็น security risk |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”Error Message ที่ไม่ Machine-readable อาการ:
{ "error": "The email address you entered is already in use" }- client ต้อง parse string เพื่อรู้ error type
- ใช้
codefield:{ "code": "EMAIL_ALREADY_EXISTS", "message": "..." }
Expose Internal Detail ใน Production Error อาการ:
{ "error": "Column 'users.email' cannot be null (SQL Error 1048)" }- เปิดเผย database schema ให้ผู้โจมตี
- filter internal detail ออกใน production:
{ "code": "VALIDATION_ERROR", "message": "Email is required" }
💡 ตัวอย่างจากของจริง
Stripe API:
- error format:
{ "error": { "type": "card_error", "code": "card_declined", "message": "...", "param": "number" } }typeบอก category,codeบอก specific error,paramบอก field ที่ผิดGitHub API:
- validation error:
{ "message": "Validation Failed", "errors": [{ "resource": "Issue", "field": "title", "code": "missing_field" }] }- machine-readable
codeทำให้ client แสดง error message เป็นภาษาของตัวเองได้