KoderKoder.ai
প্রাইসিংএন্টারপ্রাইজএডুকেশনবিনিয়োগকারীদের জন্য
লগ ইনশুরু করুন

প্রোডাক্ট

প্রাইসিংএন্টারপ্রাইজবিনিয়োগকারীদের জন্য

রিসোর্স

আমাদের সাথে যোগাযোগ করুনসহায়তাএডুকেশনব্লগ

লিগ্যাল

প্রাইভেসি পলিসিটার্মস অফ ইউজসিকিউরিটিঅ্যাকসেপ্টেবল ইউজ পলিসিঅ্যাবিউজ রিপোর্ট করুন

সোশ্যাল

LinkedInTwitter
Koder.ai
ভাষা

© 2026 Koder.ai. সর্বস্বত্ব সংরক্ষিত।

হোম›ব্লগ›স্পষ্ট ও সামঞ্জস্যপূর্ণ প্রতিক্রিয়ার জন্য Go API ত্রুটি হ্যান্ডলিং প্যাটার্ন
২৯ সেপ, ২০২৫·7 মিনিট

স্পষ্ট ও সামঞ্জস্যপূর্ণ প্রতিক্রিয়ার জন্য Go API ত্রুটি হ্যান্ডলিং প্যাটার্ন

Go API ত্রুটি হ্যান্ডলিং প্যাটার্ন যা টাইপ করা ত্রুটি, HTTP স্ট্যাটাস কোড, রিকোয়েস্ট আইডি এবং নিরাপদ বার্তা একরূপ করে — অভ্যন্তরীণ তথ্য ফাঁস করা ছাড়াই।

স্পষ্ট ও সামঞ্জস্যপূর্ণ প্রতিক্রিয়ার জন্য Go API ত্রুটি হ্যান্ডলিং প্যাটার্ন

কেন অনিয়মিত API ত্রুটি ক্লায়েন্টদের বিরক্ত করে

যখন প্রতিটি এন্ডপয়েন্ট ভিন্নভাবে ব্যর্থতা জানায়, ক্লায়েন্টরা আপনার API‑র উপর বিশ্বাস হারায়। এক রুট ফিরিয়ে দেয় { "error": "not found" }, অন্যটি দেয় { "message": "missing" }, আর তৃতীয়টি পাঠায় প্লেইন টেক্সট। যদিও অর্থ মিলতে পারে, ক্লায়েন্ট কোড এখন জুডশ করতে বাধ্য হয় কী ঘটেছে।

ব্যয় দ্রুত প্রকাশ পায়। টিমগুলো ভাঙা পার্সিং লজিক তৈরি করে এবং প্রতি এন্ডপয়েন্টে বিশেষ কেস যোগ করে। রিট্রাই ঝুঁকিপূর্ণ হয়ে যায় কারণ ক্লায়েন্ট বুঝতে পারে না “পুনরায় চেষ্টা করুন” কি “আপনার ইনপুট ভুল”। সাপোর্ট টিকিট বেড়ে যায় কারণ ক্লায়েন্ট কেবল অস্পষ্ট একটি বার্তা দেখে এবং আপনার দল সহজে সার্ভার‑সাইড লগ লাইনের সাথে মিলাতে পারে না।

একটি সাধারণ দৃশ্য: মোবাইল অ্যাপ সাইনআপের সময় তিনটি শেষপয়েন্ট কল করে। প্রথমটি HTTP 400 দিবে একটি ফিল্ড-লেভেল ত্রুটি ম্যাপ সহ, দ্বিতীয়টি HTTP 500 দিবে স্ট্যাক ট্রেস স্ট্রিং, এবং তৃতীয়টি HTTP 200 দিয়ে { "ok": false } পাঠাবে। অ্যাপ টিম তিনটা আলাদা ত্রুটি হ্যান্ডলার পাঠায়, এবং আপনার ব্যাকএন্ড টিম এখনও পায় রিপোর্ট “signup কখনও কখনও ব্যর্থ হয়” — কোথা থেকে শুরু করবেন বোঝা যায় না।

লক্ষ্য একটি পূর্বানুমানযোগ্য চুক্তি। ক্লায়েন্টদের নির্ভরযোগ্যভাবে পড়তে পারা উচিত কী ঘটেছে — সেটা তাদের ভুল নাকি আপনার, পুনরায় চেষ্টা করা উচিত কি না, আর একটি request ID যাতে তারা সাপোর্টে পেস্ট করতে পারে।

স্কোপ নোট: এখানে JSON HTTP API‑র উপর ফোকাস করা হয়েছে (gRPC নয়), কিন্তু একই ধারণা যেখানেই আপনি সিস্টেমকে ত্রুটি ফিরান সেখানে প্রযোজ্য।

একটি সহজ লক্ষ্য: প্রতিটি এন্ডপয়েন্ট এক চুক্তি মেনে চলুক

একটি স্পষ্ট চুক্তি বেছে নিন এবং প্রতিটি এন্ডপয়েন্টকে তা মানতে বাধ্য করুন। “একরকম” মানে একই JSON আকার, ক্ষেত্রগুলোর একই অর্থ, এবং একই আচরণ — কোন হ্যান্ডলার ব্যর্থ হোক না কেন। একবার এটি করলে, ক্লায়েন্টরা অনুমান করা বন্ধ করে এবং সত্যিকার হ্যান্ডলিং করতে পারে।

একটি দরকারি চুক্তি ক্লায়েন্টকে পরের পদক্ষেপ ঠিক করতে সাহায্য করে। বেশিরভাগ অ্যাপে, প্রতিটি ত্রুটি রেসপন্সকে তিনটি প্রশ্নের উত্তর দিতে হবে:

  • আমি কি আমার ইনপুট ঠিক করে পারব?
  • কি আমাকে পরে পুনরায় চেষ্টা করা উচিত?
  • কি আমাকে সাপোর্টে যোগাযোগ করতে হবে?

প্রায়োগিক নিয়মাবলি:

  • সব ত্রুটির জন্য একটি রেসপন্স স্কিমা।
  • একটি স্ট্যাটাস‑কোড নীতি (একই ত্রুটি টাইপ সবসময় একই HTTP স্ট্যাটাসে ম্যাপ হবে)।
  • একটি নিরাপদ বার্তা নীতি (কী ব্যবহারকারী দেখতে পাবে বনাম কী অভ্যন্তরীণ থাকবে)।
  • একটি করেলেশন হুক (রিকোয়েস্ট আইডি যাতে সাপোর্ট ব্যর্থতা খুঁজে পায়)।

আগে থেকেই সিদ্ধান্ত নিন কোন জিনিসগুলো কখনো রেসপন্সে দেখানো যাবে না। সাধারণ “কখনো না” আইটেমগুলোর মধ্যে থাকতে পারে SQL ফ্র্যাগমেন্ট, স্ট্যাক ট্রেস, অভ্যন্তরীণ হোস্টনেম, সিক্রেট, এবং ডিপেন্ডেন্সি‑থেকে আসা কাঁচা ত্রুটি স্ট্রিং।

একটি পরিষ্কার বিভাজন রাখুন: সংক্ষিপ্ত ব্যবহারকারী‑দৃষ্টিকোণ বার্তা (নিরাপদ, ভদ্র, কার্যনির্দেশক) এবং অভ্যন্তরীণ বিবরণ (পূর্ণ ত্রুটি, স্ট্যাক, কনটেক্সট) শুধু লগে রাখুন। উদাহরণস্বরূপ, “Could not save your changes. Please try again.” নিরাপদ। “pq: duplicate key value violates unique constraint users_email_key” নয়।

যখন সব এন্ডপয়েন্ট একই চুক্তি মেনে চলে, ক্লায়েন্ট একটিমাত্র ত্রুটি হ্যান্ডলার বানাতে পারে এবং সেটি সর্বত্র ব্যবহার করতে পারে।

ক্লায়েন্টরা নির্ভর করতে পারে এমন একটি ত্রুটি রেসপন্স স্কিমা নির্ধারণ করুন

ক্লায়েন্টরা কেবল তখনই ত্রুটিগুলো পরিষ্কারভাবে হ্যান্ডল করতে পারবে যখন প্রতিটি এন্ডপয়েন্ট একই আকারে উত্তর দেবে। একটি JSON এনভেলপ বেছে নিন এবং তা স্থিতিশীল রাখুন।

একটি ব্যবহারিক ডিফল্ট হলো একটি error অবজেক্ট প্লাস একটি শীর্ষ‑স্তরের request_id:

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Some fields are invalid.",
    "details": {
      "fields": {
        "email": "must be a valid email address"
      }
    }
  },
  "request_id": "req_01HV..."
}

HTTP স্ট্যাটাস বিস্তৃত ক্যাটাগরি দেয় (400, 401, 409, 500)। যান্ত্রিকভাবে পড়ার মতো error.code ক্লায়েন্টকে নির্দিষ্ট কেসে শাখা করার সুযোগ দেয়। এই বিভাজন গুরুত্বপূর্ণ কারণ অনেক ভিন্ন সমস্যা একই স্ট্যাটাস শেয়ার করতে পারে। মোবাইল অ্যাপ EMAIL_TAKEN বনাম WEAK_PASSWORD‑এর জন্য ভিন্ন UI দেখাতে পারে, যদিও উভয়ই 400 হতে পারে।

error.message‑কে নিরাপদ ও মানুষ-পঠনীয় রাখুন। এটি ব্যবহারকারীকে সমস্যা ঠিক করতে সাহায্য করবে, কিন্তু অভ্যন্তরীণ তথ্য (SQL, স্ট্যাক ট্রেস, প্রোভাইডার নাম, ফাইল পাথ) কখনো ফাঁস করবে না।

ঐচ্ছিক ক্ষেত্রগুলি তখনই উপকারী যদি সেগুলো পূর্বানুমানযোগ্য থাকে:

  • ভ্যালিডেশন ত্রুটি: details.fields — ফিল্ড থেকে মেসেজের ম্যাপ।
  • রেট লিমিট বা অস্থায়ী সমস্যা: details.retry_after_seconds।
  • অতিরিক্ত নির্দেশনা: details.docs_hint সাধারণ টেক্সট হিসেবে (URL নয়)।

ব্যাকওয়ার্ড কম্প্যাটিবিলিটির জন্য, error.code‑কে আপনার API চুক্তির অংশ হিসেবে বিবেচনা করুন। নতুন কোড যোগ করুন কিন্তু পুরনো মানে বদলাবেন না। শুধুমাত্র ঐচ্ছিক ক্ষেত্র যোগ করুন, এবং ধরুন ক্লায়েন্ট অচেনা ক্ষেত্রগুলো উপেক্ষা করবে।

Go তে টাইপ করা ত্রুটি: হ্যান্ডলারগুলোর জন্য পরিষ্কার মডেল

ত্রুটি হ্যান্ডলিং ঝামেলার মধ্যে পড়ে যখন প্রতিটি হ্যান্ডলার ব্যর্থতা জানাতে নিজের উপায় উদ্ভাবন করে। একটি ছোট সেট টাইপ করা ত্রুটি এই সমস্যা ঠিক করে: হ্যান্ডলারগুলো জানাবে পরিচিত ত্রুটি টাইপ, এবং একটি একক রেসপন্স লেয়ার সেগুলোকে একরকম রেসপন্সে রূপান্তর করবে।

একটি ব্যবহারিক শুরু সেট বেশিরভাগ এন্ডপয়েন্ট কভার করে:

  • ValidationError (খারাপ ইনপুট)
  • NotFoundError (রিসোর্স নেই)
  • ConflictError (ইউনিক কনস্ট্রেইন্ট, স্টেট মিসম্যাচ)
  • UnauthorizedError (লগ ইন করা নেই বা অনুমোদন নেই)
  • InternalError (অন্যান্য সব)

কীটি হল শীর্ষ পর্যায়ে স্থিতিশীলতা, এমনকি মূল কারণ বদলালেও। আপনি নিম্ন‑স্তরের ত্রুটি (SQL, নেটওয়ার্ক, JSON পার্সিং) মোড়াতে পারেন, তবুও একই পাবলিক টাইপ রিটার্ন করতে পারবেন যেটা মিডলওয়্যার শনাক্ত করে।

type NotFoundError struct {
	Resource string
	ID       string
	Err      error // private cause
}

func (e NotFoundError) Error() string { return "not found" }
func (e NotFoundError) Unwrap() error { return e.Err }

আপনার হ্যান্ডলারে, sql.ErrNoRows সরাসরি লিক না করে NotFoundError{Resource: "user", ID: id, Err: err} রিটার্ন করুন।

ত্রুটি চেক করার জন্য errors.As ব্যবহার করুন কাস্টম টাইপগুলির জন্য এবং errors.Is ব্যবহার করুন সেন্টিনেল ত্রুটির জন্য। সেন্টিনেল ত্রুটি (যেমন var ErrUnauthorized = errors.New("unauthorized")) সরল কেসে কাজ করে, কিন্তু কাস্টম টাইপগুলো জিতবে যখন আপনাকে নিরাপদ কনটেক্সট (যেমন কোন রিসোর্সটি মিসিং ছিল) প্রয়োজন হবে — তা আপনার পাবলিক রেসপন্স চুক্তি বদলায় না।

সংযুক্ত করার বিষয়ে কড়া থাকুন:

  • পাবলিক (ক্লায়েন্টের জন্য নিরাপদ): সংক্ষিপ্ত বার্তা, একটি স্থিতিশীল কোড, এবং কখনো কখনো ভ্যালিডেশন ফিল্ড নাম।
  • প্রাইভেট (শুধু লগে): অন্তর্নিহিত Err, স্ট্যাক ইনফো, কাঁচা SQL ত্রুটি, টোকেন, ব্যবহারকারীর ডাটা।

এই বিভাজন আপনাকে ক্লায়েন্টকে সাহায্য করতে দেয় অভ্যন্তরীণ তথ্য প্রকাশ না করে।

ত্রুটি টাইপগুলোকে ধারাবাহিকভাবে HTTP স্ট্যাটাস কোডে ম্যাপ করুন

একবার আপনার কাছে টাইপ করা ত্রুটি থাকলে, পরবর্তী কাজ হলো দরকারি কিন্তু নীরস: একই ত্রুটি টাইপ সবসময় একই HTTP স্ট্যাটাস উৎপন্ন করবে। ক্লায়েন্টরা এর উপর লজিক তৈরি করবে।

একটি ব্যবহারিক ম্যাপিং যা বেশিরভাগ API‑র জন্য কাজ করে:

Error type (example)StatusWhen to use it
BadRequest (malformed JSON, missing required query param)400The request is not valid at a basic protocol or format level.
Unauthenticated (no/invalid token)401The client needs to authenticate.
Forbidden (no permission)403Auth is valid, but access is not allowed.
NotFound (resource ID does not exist)404The requested resource is not there (or you choose to hide existence).
Conflict (unique constraint, version mismatch)409The request is well-formed, but it clashes with current state.
ValidationFailed (field rules)422The shape is fine, but business validation fails (email format, min length).
RateLimited429Too many requests in a time window.
Internal (unknown error)500Bug or unexpected failure.
Unavailable (dependency down, timeout, maintenance)503Temporary server-side issue.

দুইটি পার্থক্য যা অনেক বিভ্রান্তি রোধ করে:

  • 400 বনাম 422: 400 ব্যবহার করুন যখন আপনি রিকোয়েস্ট নির্ভরযোগ্যভাবে ব্যাখ্যা করতে পারেন না (ভুল JSON, ভুল টাইপ)। 422 ব্যবহার করুন যখন আপনি এটি পার্স করতে পারেন, কিন্তু মান গ্রহণযোগ্য নয়।
  • 409 বনাম 422: 422 ব্যবহার করুন ক্ষেত্র-স্তরের ভ্যালিডেশনের জন্য (পাসওয়ার্ড সংক্ষিপ্ত)। 409 ব্যবহার করুন যখন ডেটা সঠিক কিন্তু অ্যাপ্লাই করা যায় না কারণ সার্ভারের স্টেট বিরোধী (ইমেল আগে থেকেই আছে, অর্ডার আগে থেকেই শিপ হয়েছে)।

রিট্রাই নির্দেশনা গুরুত্বপূর্ণ:

  • সাধারণত নিরাপদ রিট্রাই: 503, এবং কখনো কখনো 429 (অপেক্ষার পর)।
  • সাধারণত পরিবর্তন ছাড়া পুনরায় চেষ্টা করা নিরাপদ নয়: 400, 401, 403, 404, 409, 422।
  • যদি অপারেশন idempotent হয় (একই বডি সহ PUT, বা POST with idempotency key), তখন ট্রানজিয়েন্ট ব্যর্থতার পরে রিট্রাই আরও নিরাপদ হয়ে ওঠে।

রিকোয়েস্ট আইডি: ক্লায়েন্ট সমস্যা ডিবাগ করার দ্রুততম উপায়

ডিফল্টভাবে রিকোয়েস্ট আইডি যোগ করুন
এন্ড টু এন্ড রিকোয়েস্ট আইডি যোগ করুন যাতে সাপোর্ট অভ্যন্তরীণ তথ্য ফাঁস না করে সমস্যার ট্রেস করতে পারে।
API তৈরি করুন

একটি রিকোয়েস্ট আইডি হল ছোট একটি ইউনিক মান যা এক API কলের end-to-end পরিচয় দেয়। ক্লায়েন্টরা যদি প্রতিটি রেসপন্সে এটি দেখতে পায়, সাপোর্ট সহজ হয়ে যায়: “আমাকে রিকোয়েস্ট আইডিটি পাঠান” প্রায়ই যথেষ্ট হয় সঠিক লগ এবং ব্যর্থতা খুঁজে পেতে।

এই অভ্যাস সফল এবং ত্রুটি উভয় রেসপন্সেই উপকার দেয়।

তৈরি ও প্রোপাগেশন নিয়ম

একটি স্পষ্ট নিয়ম ব্যবহার করুন: ক্লায়েন্ট যদি রিকোয়েস্ট আইডি পাঠায়, রাখুন। না পাঠালে নতুন তৈরি করুন।

  • একটি একক হেডার নাম থেকে ইনকামিং ID গ্রহণ করুন (একটি নাম বেছে নিন এবং ডকুমেন্ট করুন, উদাহরণস্বরূপ X-Request-Id).
  • হেডার অনুপস্থিত বা খালি হলে, এজে (middleware) নতুন একটি ID তৈরি করে রিকোয়েস্ট কনটেক্সটে জোড়া দিন।
  • রিকোয়েস্টের মধ্যেই কখনো ID পরিবর্তন করবেন না। কনটেক্সট বা হেডার মাধ্যমে ডাউনস্ট্রিম কলগুলোতেও পাঠিয়ে দিন।

রিকোয়েস্ট আইডি তিন জায়গায় রাখুন:

  • রেসপন্স হেডার (আপনি যেই হেডার নাম গ্রহণ করেন সেটাই ব্যবহার করুন)
  • রেসপন্স বডি (স্ট্যান্ডার্ড স্কিমায় request_id হিসাবে)
  • লগ (প্রতিটি লগ লাইনে স্ট্রাকচার্ড ফিল্ড হিসেবে)

ব্যাচ ও অ্যাসিঙ্ক কাজ

ব্যাচ এন্ডপয়েন্ট বা ব্যাকগ্রাউন্ড জবগুলোর জন্য একটি প্যারেন্ট রিকোয়েস্ট আইডি রাখুন। উদাহরণ: ক্লায়েন্ট 200 সারি আপলোড করে, 12টি ভ্যালিডেশন ফেইল করে, এবং আপনি কাজ এনকিউ করেন। পুরো কলের জন্য একটি request_id রিটার্ন করুন, এবং প্রতিটি জব বা প্রতিটি আইটেম ত্রুটিতে parent_request_id যোগ করুন। এভাবে আপনি একবারের আপলোডকে ট্রেস করতে পারবেন এমনকি যখন এটি বহু টাসকে ফ্যান‑আউট করে।

লগিং ও মেট্রিক্স অভ্যন্তরীণ তথ্য ফাঁস করা ছাড়াই

ক্লায়েন্টদের একটি স্পষ্ট, স্থির ত্রুটি রেসপন্স দরকার। আপনার লগগুলোকে দরকার messy‑তথ্য দরকার। সেই দুইটির মাঝে বিচ্ছিন্নতা রাখুন: ক্লায়েন্টকে নিরাপদ বার্তা ও পাবলিক কোড দিন, সার্ভারে অভ্যন্তরীণ কারণ, স্ট্যাক, ও কনটেক্সট লগ করুন।

প্রতি ত্রুটি রেসপন্সের জন্য একটি স্ট্রাকচার্ড ইভেন্ট লগ করুন, সেটা request_id দিয়ে সার্চ করা যাবে।

যেগুলো নিয়মিত রাখতে চান:

  • request_id
  • user_id বা account_id (যদি অথেন্টিকেটেড থাকে)
  • পাবলিক error code এবং HTTP status
  • handler/route নাম ও মেথড
  • অভ্যন্তরীণ ত্রুটি বিবরণ (wrapped cause, validation field errors, upstream timeout)

অভ্যন্তরীণ বিবরণ শুধু সার্ভার লগে (বা একটি অভ্যন্তরীণ ত্রুটি স্টোরে) রাখুন। ক্লায়েন্ট কখনোই কাঁচা ডাটাবেস ত্রুটি, কুয়েরি টেক্সট, স্ট্যাক ট্রেস বা প্রোভাইডার মেসেজ দেখবে না। যদি আপনার বহু সার্ভিস থাকে, একটি অভ্যন্তরীণ ফিল্ড যেমন source (api, db, auth, upstream) ট্রায়াজ দ্রুত করতে সাহায্য করে।

নয়েজি এন্ডপয়েন্ট ও রেট‑লিমিট ত্রুটিগুলোর দিকে নজর রাখুন। যদি কোনো এন্ডপয়েন্ট হাজার হাজার বার প্রতি মিনিটে একই 429 বা 400 তৈরি করে, লগ স্প্যাম থেকে বিরত থাকবার জন্য ইভেন্টগুলো স্যাম্পল করুন, অথবা প্রত্যাশিত ত্রুটির ক্ষেত্রে সেভিরিটি লো করে দিন—তবুও মেট্রিক্সে তাদের কাউন্ট রাখুন।

মেট্রিক্স সমস্যা লগের থেকে আগে ধরে ফেলে। HTTP স্ট্যাটাস এবং ত্রুটি কোড গ্রুপ করে কাউন্ট ট্র্যাক করুন, এবং হঠাৎ স্পাইক‑এ অ্যালার্ট দিন। যদি RATE_LIMITED ডিপ্লয়মেন্টের পরে 10x বৃদ্ধি পায়, আপনি সেটি দ্রুত দেখবেন যদিও লগ স্যাম্পল করা হয়েছে।

ধাপে ধাপে: Go তে একটি স্থিতিশীল ত্রুটি পাইপলাইন বাস্তবায়ন

ত্রুটি হ্যান্ডলিং কেন্দ্রীভূত করুন
আপনার টাইপ করা ত্রুটি মডেলকে একটি শেয়ার করা ম্যাপার লেয়ারে রূপান্তর করুন যা সকল এন্ডপয়েন্টে ব্যবহার করা যায়।
ব্যাকএন্ড তৈরি করুন

ত্রুটিগুলো সামঞ্জস্যপূর্ণ করার সহজতম উপায় হলো সেগুলোকে "সব জায়গায়" হ্যান্ডল করা বন্ধ করে ছোট একটি পাইপলাইনের মাধ্যমে রুট করা। সেই পাইপলাইন ঠিক করে দেয় ক্লায়েন্ট কী দেখবে এবং কী আপনি লগে রাখবেন।

৫টি ব্যবহারিক ধাপে পাইপলাইন

একটি ছোট সেট ত্রুটি কোড দিয়ে শুরু করুন যা ক্লায়েন্ট নির্ভর করতে পারে (উদাহরণ: INVALID_ARGUMENT, NOT_FOUND, UNAUTHORIZED, CONFLICT, INTERNAL)। সেগুলোকে টাইপ করা ত্রুটিতে মোড়ান যেগুলো শুধুমাত্র নিরাপদ, পাবলিক ফিল্ড উন্মুক্ত করে (code, safe message, ঐচ্ছিক details)। অভ্যন্তরীণ কারণ গোপন রাখুন।

এরপর একটি ট্রান্সলেটর ফাংশন তৈরি করুন যা যেকোনো ত্রুটিকে (statusCode, responseBody)‑তে বদলে দেয়। এখানেই টাইপ করা ত্রুটিগুলো HTTP স্ট্যাটাসে ম্যাপ হয়, এবং অজানা ত্রুটি নিরাপদ 500 রেসপন্সে পরিণত হয়।

পরবর্তী, মিডলওয়্যার যোগ করুন যা:

  • নিশ্চিত করে প্রতিটি রিকোয়েস্টে একটি request_id আছে
  • panic থেকে recover করে

একটি panic কখনো ক্লায়েন্টকে স্ট্যাক ট্রেস ডাম্প করা উচিত নয়। সাধারণ একটি 500 রেসপন্স রিটার্ন করুন একটি জেনেরিক মেসেজসহ, এবং একই request_id দিয়ে পুরো panic‑টি সম্পূর্ণভাবে লগ করুন।

শেষে, আপনার হ্যান্ডলারেরা রেসপন্স লিখার পরিবর্তে error রিটার্ন করবে। একটি র‍্যাপার হ্যান্ডলার হোক যা হ্যান্ডলার কল করে, ট্রান্সলেটর চালায়, এবং স্ট্যান্ডার্ড ফর্ম্যাটে JSON লিখে।

একটি সংক্ষিপ্ত চেকলিস্ট:

  • নিরাপদ ফিল্ড ও স্থিতিশীল কোড সহ টাইপ করা ত্রুটি সংজ্ঞা করুন।
  • এক জায়গায় ত্রুটিকে স্ট্যাটাস ও রেসপন্স JSON‑এ ট্রান্সলেট করুন।
  • রিকোয়েস্ট আইডি এবং panic recovery মিডলওয়্যার যোগ করুন।
  • হ্যান্ডলারগুলোকে রেসপন্স লেখার বদলে ত্রুটি রিটার্ন করান।
  • ট্রান্সলেটর ও র‍্যাপারের জন্য গোল্ডেন টেস্ট যোগ করুন।

গোল্ডেন টেস্ট গুরুত্বপূর্ণ কারণ সেগুলো চুক্তি লক করে। কেউ পরে যদি মেসেজ বা স্ট্যাটাস কোড বদলে দেয়, টেস্ট ফেল করবে ক্লায়েন্টদের অবাক হওয়ার আগে।

উদাহরণ: একটি এন্ডপয়েন্ট, তিনটি ব্যর্থতা, পূর্বানুমানযোগ্য রেসপন্স

ধরা যাক একটি এন্ডপয়েন্ট: ক্লায়েন্ট একটি কাস্টমার রেকর্ড তৈরি করে।

POST /v1/customers JSON { "email": "[email protected]", "name": "Pat" } পাঠানো হলে সার্ভার সবসময় একই ত্রুটি আকার রিটার্ন করে এবং সবসময় request_id অন্তর্ভুক্ত করে।

1) ভ্যালিডেশন ত্রুটি (400)

ইমেল অনুপস্থিত বা ভুল ফরম্যাটে। ক্লায়েন্ট ফিল্ড হাইলাইট করতে পারে।

{
  "request_id": "req_01HV9N2K6Q7A3W1J9K8B",
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Some fields need attention.",
    "details": {
      "fields": {
        "email": "must be a valid email address"
      }
    }
  }
}

2) কনফ্লিক্ট (409)

ইমেল আগেই আছে। ক্লায়েন্টকে সাইন ইন করার বা অন্য ইমেল বেছে নেওয়ার পরামর্শ দেওয়া যায়।

{
  "request_id": "req_01HV9N3C2D0F0M3Q7Z9R",
  "error": {
    "code": "ALREADY_EXISTS",
    "message": "A customer with this email already exists."
  }
}

3) অস্থায়ী ব্যর্থতা (503)

কোনো ডিপেন্ডেন্সি ডাউন আছে। ক্লায়েন্ট ব্যাকঅফ নিয়ে পুনরায় চেষ্টা করতে পারে এবং শান্তভাবে একটি মেসেজ দেখাতে পারে।

{
  "request_id": "req_01HV9N3X8P2J7T4N6C1D",
  "error": {
    "code": "TEMPORARILY_UNAVAILABLE",
    "message": "We could not save your request right now. Please try again."
  }
}

একটি চুক্তি থাকলে ক্লায়েন্টের প্রতিক্রিয়া ধারাবাহিক হয়:

  • 400: details.fields ব্যবহার করে ফিল্ডগুলো চিহ্নিত করবে
  • 409: ব্যবহারকারীকে একটি নিরাপদ পরবর্তী ধাপ দেখাবে
  • 503: রিট্রাই প্রম্পট করবে এবং request_id‑কে সাপোর্ট আইডি হিসেবে দেখাবে

সাপোর্টের জন্য একই request_id অভ্যন্তরীণ লগে আসল কারণ পর্যন্ত সরাসরি পথ সরবরাহ করে, স্ট্যাক ট্রেস বা ডাটাবেস ত্রুটি ফাঁস না করেই।

সাধারণ ফাঁদগুলো যা ত্রুটি হ্যান্ডলিং খারাপ করে

ক্লায়েন্টদের বিরক্ত করার দ্রুততম উপায় হলো তাদের অনুমান করতে বাধ্য করা। যদি এক এন্ডপয়েন্ট { "error": "..." } ফেরায় আর অন্যটি { "message": "..." }, প্রতি ক্লায়েন্ট একজোড়া বিশেষ কেসে পরিণত হয় এবং বাগ সপ্তাহ ধরে লুকিয়ে থাকে।

কয়েকটি ভুল বারবার দেখা যায়:

  • ত্রুটিগুলিকে 200 দিয়ে ফেরানো, বা একাধিক ত্রুটি স্কিমের মাঝে সুইচ করা।
  • ব্যবহারকারী মেসেজে অভ্যন্তরীণ তথ্য প্রকাশ করা: SQL ত্রুটি, স্ট্যাক ট্রেস, IP, হোস্টনেম, বা ফাইল পাথ।
  • কেবল মানব‑পাঠ্যকে শনাক্তকারী হিসেবে ব্যবহার করা, স্থির code না থাকা।
  • ত্রুটি কোডগুলি সাবধানতা ছাড়া বদলানো বা একই কোড বিভিন্ন সমস্যার জন্য পুনরায় ব্যবহার করা।
  • ত্রুটি‑কালে মাত্র request_id যোগ করা, ফলে সফল কলগুলির সাথে সম্পর্ক করা যায় না।

অভ্যন্তরীণ তথ্য ফাঁস করা সবচেয়ে সহজ ফাঁদ। একটি হ্যান্ডলার কেবল err.Error() রিটার্ন করে দিলে একটি কনস্ট্রেইন্ট নাম বা থার্ড‑পার্টি মেসেজ প্রোডাকশনে চলে যায়। ক্লায়েন্ট মেসেজ নিরাপদ ও সংক্ষিপ্ত রাখুন, বিস্তারিত কারণ লগে রাখুন।

শুধু টেক্সটের উপর নির্ভর করাও ধীরে ধীরে সমস্যা করে। যদি ক্লায়েন্টকে ইংরেজি বাক্যগুলো পার্স করে “email already exists”‑এর মতো নির্ণয় করতে হয়, আপনি মেসেজ বদলে দিলে লজিক ভেঙে পড়বে। স্থিতিশীল ত্রুটি কোড আপনাকে মেসেজ পরিবর্তন, অনুবাদ, এবং আচরণ বজায় রাখার স্বাধীনতা দেয়।

ত্রুটি কোডকে আপনার পাবলিক চুক্তির অংশ হিসেবে বিবেচনা করুন। যদি বদলাতে হয়, একটি নতুন কোড যোগ করুন এবং পুরনো কোডকে কিছু সময় ধরে কাজ করতেই দিন, এমনকি যদি উভয়ই একই HTTP স্ট্যাটাসে ম্যাপ করে।

শেষে, প্রতিটি রেসপন্সে একই request_id ফিল্ড রাখুন, সাফল্য বা ব্যর্থতা—যখন ব্যবহারকারী বলে “এটা কাজ করছিল, পরে ভেঙে গেল”, সেই একটি আইডি প্রায়শই এক ঘণ্টার গেসিং বাঁচায়।

শিপ করার আগে দ্রুত চেকলিস্ট

আপনার ত্রুটি চুক্তি পরিকল্পনা করুন
Koder.ai planning mode-এ একটি একরকম JSON ত্রুটি চুক্তি এবং রিকোয়েস্ট আইডি নীতি খসড়া করুন।
বিনামূল্যে চেষ্টা করুন

রিলিজের আগে একটি দ্রুত কনসিস্টেন্সি পরীক্ষা করুন:

  • সব জায়গায় একই ত্রুটি আকার। প্রতিটি এন্ডপয়েন্ট একই JSON ফিল্ড রিটার্ন করে (উদাহরণ: error.code, error.message, request_id)।
  • স্থিতিশীল ত্রুটি কোড ও কভারেজ। কোডগুলো সংক্ষিপ্ত ও স্পষ্ট রাখুন (VALIDATION_FAILED, NOT_FOUND, CONFLICT, UNAUTHORIZED)। এমন টেস্ট রাখুন যেন হ্যান্ডলার অচেনা কোড রিটার্ন করতে না পারে।
  • একটি স্ট্যাটাস ম্যাপিং রুলবুক। প্রতিটি ত্রুটি টাইপ কোন HTTP স্ট্যাটাসে যাবে তা এক জায়গায় নির্ধারণ করুন এবং শেয়ার করুন।
  • রিকোয়েস্ট আইডি উভয় দিকে। প্রতিটি রেসপন্সে request_id রিটার্ন করুন এবং প্রতিটি রিকোয়েস্টের লগে সেটি রাখুন, এমনকি panic ও টাইমআউট কেসেও।
  • ডিফল্টভাবে নিরাপদ মেসেজ। ব্যবহারকারী‑মুখী মেসেজ সংক্ষিপ্ত, স্পষ্ট, এবং কার্যনির্দেশক হওয়া উচিত—কখনো স্ট্যাক ট্রেস, SQL ত্রুটি, বা ভেন্ডর নাম নয়।

তারপর কয়েকটি এন্ডপয়েন্ট মানুয়ালি স্পট‑চেক করুন। একটি ভ্যালিডেশন ত্রুটি, একটি মিসিং রেকর্ড, এবং একটি অনাকাঙ্ক্ষিত ব্যর্থতা ট্রিগার করুন। যদি প্রতিক্রিয়াগুলো এন্ডপয়েন্ট জুড়ে ভিন্ন দেখায় (ফিল্ড বদলে, স্ট্যাটাস কোড বিচ্যুত হয়, মেসেজ অতিরিক্ত তথ্য ফাঁস করে), শেয়ার করা পাইপলাইন ঠিক করুন নতুন ফিচার যোগ করার আগে।

প্রায়োগিক নিয়ম: যদি কোনো মেসেজ একটি আক্রমণকারীকে সাহায্য করবে বা স্বাভাবিক ব্যবহারকারীকে বিভ্রান্ত করবে, তা লগে রাখুন — রেসপন্সে নয়।

পরবর্তী পদক্ষেপ: এখনই স্ট্যান্ডার্ড করুন এবং পরে ধারাবাহিক রাখুন

আপনি চাইলে API আগে থেকেই লাইভ থাকুক, তবুও একটি শেয়ার করা ত্রুটি চুক্তি (স্ট্যাটাস, স্থিতিশীল ত্রুটি কোড, নিরাপদ মেসেজ, এবং request_id) লিখে রাখুন। এটি ক্লায়েন্টদের জন্য ত্রুটিগুলো পূর্বানুমানযোগ্য করে তোলার দ্রুততম উপায়।

তারপর ধীরেই মাইগ্রেট করুন। বিদ্যমান হ্যান্ডলারগুলো রাখতে পারেন, কিন্তু তাদের ব্যর্থতাগুলোকে এক ম্যাপারের মাধ্যমে রুট করুন যা অভ্যন্তরীণ ত্রুটিকে আপনার পাবলিক রেসপন্স আকারে রূপান্তর করবে। এটি ঝুঁকিপূর্ণ বড় রিফ্যাক্টরের প্রয়োজন ছাড়াই সামঞ্জস্য বাড়ায় এবং নতুন এন্ডপয়েন্টগুলোকে নতুন ফরম্যাট উদ্ভাবন করা থেকে রোধ করে।

একটি ছোট ত্রুটি কোড ক্যাটালগ রাখুন এবং সেটিকে API‑এর অংশ হিসেবে আচরণ করুন। কেউ নতুন কোড যোগ করতে চাইলে দ্রুত রিভিউ করুন: এটা কি সত্যিই নতুন, নাম স্পষ্ট কি না, এবং ঠিক HTTP স্ট্যাটাসে ম্যাপ হচ্ছে কি না।

কয়েকটি টেস্ট যোগ করুন যা ড্রিফট আটকায়:

  • প্রতিটি ত্রুটি রেসপন্সে request_id আছে।
  • স্ট্যাটাস কোড ত্রুটি টাইপের সাথে মেলে (টেক্সট নয়)।
  • error.code উপস্থিত এবং ক্যাটালগের অংশ।
  • error.message নিরাপদ এবং কখনো অভ্যন্তরীণ বিবরণ নেই।
  • অজানা ত্রুটি 500‑এ ফলোব্যাক করে একটি জেনেরিক মেসেজ দেয়।

যদি আপনি সম্পূর্ণ নতুন Go ব্যাকএন্ড বানান, শুরুতেই কনট্র্যাক্ট লক করে রাখা সাহায্য করে। উদাহরণস্বরূপ, Koder.ai (koder.ai)‑এ একটি planning mode আছে যেখানে আপনি ত্রুটি স্কিমা ও কোড ক্যাটালগ আগে থেকেই নির্ধারণ করে রাখতে পারেন, তারপর API বাড়ার সাথে সাথে হ্যান্ডলারগুলোকে সামঞ্জস্য রাখতে পারবেন।

সাধারণ প্রশ্ন

What should a “consistent error response” look like?

একটি JSON ফর্ম্যাট সব এন্ডপয়েন্টে একইভাবে ব্যবহার করুন। একটি বাস্তবসম্মত ডিফল্ট হচ্ছে শীর্ষ স্তরের request_id এবং একটি error অবজেক্ট যাতে থাকে code, message, এবং ঐচ্ছিক details — যাতে ক্লায়েন্ট নির্ভুলভাবে পার্স করে প্রতিক্রিয়া অনুযায়ী কাজ করতে পারে।

How do I avoid leaking internal details in API errors?

error.message‑কে সংক্ষিপ্ত ও ব্যবহারকারী-বান্ধব বাক্য হিসাবে রাখুন এবং প্রকৃত কারণ সার্ভারের লগে রাখুন। কাঁচা ডেটাবেস ত্রুটি, স্ট্যাক ট্রেস, অভ্যন্তরীণ হোস্টনেম বা তৃতীয়‑পক্ষের বার্তা কখনোই রেসপন্সে পাঠাবেন না — উন্নয়নের সময়ও অবশেষে সেটা প্রোডাকশনে চলে যেতে পারে।

Do I really need an error code if I already have HTTP status codes?

HTTP স্ট্যাটাস ব্রড ক্যাটাগরি বোঝায়, কিন্তু যান্ত্রিক লজিকের জন্য স্থির error.code খুব জরুরী। ক্লায়েন্টরা মেশিন‑রিডেবল error.code (যেমন ALREADY_EXISTS) অনুসরণ করে শাখা করতে পারে, স্ট্যাটাস কেবল সাধারণ নির্দেশ দেয় (উদাহরণ: 409 রাজ্য সংক্রান্ত সংঘাত বোঝায়)।

When should I use HTTP 400 vs 422?

400 ব্যবহার করুন যখন রিকোয়েস্ট সঠিকভাবে পার্স বা ব্যাখ্যা করা যায় না (ম্যালফর্মড JSON, ভুল টাইপ)। 422 ব্যবহার করুন যখন রিকোয়েস্ট সঠিকভাবে পার্স হয়েছে কিন্তু ব্যবসায়িক নিয়ম ভেঙে (যেমন ইমেল ফরম্যাট ভুল, পাসওয়ার্ড খুব ছোট)।

When should I use HTTP 409 vs 422?

409 ব্যবহার করুন যখন ইনপুটটি সঠিক কিন্তু সার্ভারের বর্তমান অবস্থা সঙ্গে সংঘর্ষ করছে (ইমেল ইতিমধ্যে আছে, ভার্সন মিলছে না)। 422 ব্যবহার করুন ক্ষেত্র-স্তরের ভ্যালিডেশন জন্য যেখানে মান পরিবর্তন করলেই সমস্যা দূর হয়।

How do typed errors in Go help keep responses consistent?

একটি ছোট সেট টাইপ করা ত্রুটি তৈরি করুন (validation, not found, conflict, unauthorized, internal) এবং হ্যান্ডলারেরা সেগুলো রিটার্ন করুক। পরে একটি শেয়ার করা ট্রান্সলেটর সেই টাইপগুলোকে HTTP স্ট্যাটাস ও স্ট্যান্ডার্ড JSON আউটপুটে ম্যাপ করবে — ফলে প্রতিক্রিয়া স্থিতিশীল থাকে।

How should I generate and return request IDs?

প্রতিটি রেসপন্সে request_id রিটার্ন করুন, সাফল্য হোক বা ব্যর্থতা, এবং প্রতিটি সার্ভার লগ লাইনে সেটি লগ করুন। কোন ব্যবহারকারী সমস্যা জানান, সেটি এক বাড়তি আইডি পাঠালে ওই ID দিয়েই সঠিক লগ লাইন খুঁজে পাওয়া যায়।

Why is returning HTTP 200 with `{ "ok": false }` a bad idea?

কেবলমাত্র যখন অপারেশন সফল তখনই 200 রিটার্ন করুন। ত্রুটির ক্ষেত্রে উপযুক্ত 4xx/5xx ব্যবহার করুন। 200‑এর ভেতর { "ok": false } রাখলে ক্লায়েন্টকে বডি পার্স করতে বাধ্য করে এবং inconsistent আচরণ সৃষ্টি করে।

Which errors should clients retry, and which should they not?

সাধারণভাবে retry করা ঠিক নয়: 400, 401, 403, 404, 409, 422 — কারণ এগুলোতে ক্লায়েন্ট‑সাইড পরিবর্তন ছাড়া পুনরায় চেষ্টা কাজে আসে না। 503 সাধারণত retry‑যোগ্য, এবং 429 কখনো কখনো (প্রতিশ্রুতি বা ব্যাকঅফের পর) retry করা যায়; idempotency key থাকলে POST‑ও পুনরাবৃত্তি নিরাপদ হতে পারে।

How do I prevent error responses from drifting as the API evolves?

কিছু “গোল্ডেন” টেস্ট রাখুন যা কনট্র্যাক্ট লক করে: প্রতিটি ত্রুটি রেসপন্সে request_id আছে কিনা; স্ট্যাটাস কোড টাইপ‑এর সাথে মিলে কি না; error.code ক্যাটালগের অংশ কিনা। নতুন কোড যোগ করলে পুরনো আচরণ ভেঙে গেলে টেস্ট ফেল করবে, ফলে ক্লায়েন্ট অবাক হবে না।

সূচিপত্র
কেন অনিয়মিত API ত্রুটি ক্লায়েন্টদের বিরক্ত করেএকটি সহজ লক্ষ্য: প্রতিটি এন্ডপয়েন্ট এক চুক্তি মেনে চলুকক্লায়েন্টরা নির্ভর করতে পারে এমন একটি ত্রুটি রেসপন্স স্কিমা নির্ধারণ করুনGo তে টাইপ করা ত্রুটি: হ্যান্ডলারগুলোর জন্য পরিষ্কার মডেলত্রুটি টাইপগুলোকে ধারাবাহিকভাবে HTTP স্ট্যাটাস কোডে ম্যাপ করুনরিকোয়েস্ট আইডি: ক্লায়েন্ট সমস্যা ডিবাগ করার দ্রুততম উপায়লগিং ও মেট্রিক্স অভ্যন্তরীণ তথ্য ফাঁস করা ছাড়াইধাপে ধাপে: Go তে একটি স্থিতিশীল ত্রুটি পাইপলাইন বাস্তবায়নউদাহরণ: একটি এন্ডপয়েন্ট, তিনটি ব্যর্থতা, পূর্বানুমানযোগ্য রেসপন্সসাধারণ ফাঁদগুলো যা ত্রুটি হ্যান্ডলিং খারাপ করেশিপ করার আগে দ্রুত চেকলিস্টপরবর্তী পদক্ষেপ: এখনই স্ট্যান্ডার্ড করুন এবং পরে ধারাবাহিক রাখুনসাধারণ প্রশ্ন
শেয়ার
Koder.ai
Koder দিয়ে আপনার নিজের অ্যাপ তৈরি করুন আজই!

Koder-এর শক্তি বুঝতে সবচেয়ে ভালো উপায় হলো নিজে দেখা।

বিনামূল্যে শুরু করুনডেমো বুক করুন