Always check ok first. Only then read result (on success) or description + error_code (on failure).
Overview
All methods return the same envelope, so you can write one parser and reuse it everywhere.
// success
{ "ok": true, "result": { ... } }// failure
{ "ok": false, "description": "Human-readable error", "error_code": 401 }
Error codes
Code | Meaning | Typical cause & action |
400 | Bad request | Missing field or message does not exist — fix parameters. |
401 | Unauthorized | Token invalid or revoked — check the token. |
403 | Forbidden | Insufficient permission or message ownership. |
409 | Conflict | getUpdates called while a webhook is enabled. |
429 | Rate limited | Over 30 req/s — back off and retry. |
500 | Server error | Temporary platform issue — retryable. |
50001 | MP business error | Rejected by business logic — read |
501 | Not implemented | Method not currently supported (see the method matrix). |
Handling a 409
Call getWebhookInfo to confirm the webhook configuration. Do not run deleteWebhook yourself — it is a high-risk controlled operation. Contact the maintainer to resolve the conflict.
Error-handling example
const data = await res.json();
if (!data.ok) {
console.error({ error_code: data.error_code, description: data.description });
throw new Error(`Bot API ${data.error_code}: ${data.description}`);
}
return data.result;
Retry strategy
429, 500: retry with capped exponential backoff.
400, 401, 403: do not retry — fix input or permissions.
409: reconcile polling vs webhook first.
Related
Never log full tokens or sensitive fields in error reports. See the production checklist for redaction rules.
