Telegram Bot API · error code

Telegram error 400: Bad Request: BUTTON_DATA_INVALID

Permanent - do not retryHTTP 400400 Bad Request: identifiers, content and rights

Last verified against Telegram Bot API reference

What Telegram returns
Bad Request: BUTTON_DATA_INVALID

What error 400 means

An inline keyboard button's callback_data does not meet the Bot API rule: 1 to 64 bytes. Exceeding 64 bytes, or sending an empty string, triggers this raw server error and rejects the whole message or edit. The limit is in bytes, so 64 characters of non-ASCII text can be far more than 64 bytes.

Developers hit this when they try to pack meaningful state into the button: a JSON object, a UUID plus an action, a product name, or a serialized filter. Telegram intends callback_data to be a short key, not a payload.

Nothing is wrong with the message text itself, and the chat is fine. Fix the keyboard and resend.

What it looks like

{"ok":false,"error_code":400,"description":"Bad Request: BUTTON_DATA_INVALID"}

Why it happens

  • Serialized JSON or multiple IDs concatenated into callback_data.
  • UUIDs (36 chars) combined with prefixes and separators exceeding 64 bytes.
  • Multi-byte characters pushing a 'short' string over the byte limit.
  • An empty callback_data from a template branch.

How to fix Telegram error 400

  1. 1Measure len(callback_data.encode('utf-8')) for every button; keep it at or below 64.
  2. 2Store state server-side and put only a short opaque key (for example a:123) in the button.
  3. 3Use compact encodings (base64url of binary IDs) when you must carry more than one field.
  4. 4Add a validation step in your keyboard builder that fails loudly in development.
  5. 5If you edited an existing keyboard, note that every button in the new markup is validated, not only the one you changed.

How to stop it recurring

Treat callback_data as a lookup key. A small table mapping keys to action payloads keeps buttons tiny and lets you change behaviour without resending keyboards. Enforce the 64-byte rule in one shared function, and include a test that builds your largest real keyboard and asserts every button passes. Keep prefixes short (one or two characters) so the remaining bytes are available for identifiers.

The byte budget and its neighbors (copy_text 1-256 characters, callback answer text 0-200 characters) are tabulated under keyboard and callback limits. When the URL field rather than the data field is the problem, the API answers with BUTTON_URL_INVALID instead.

Official reference: Telegram Bot API reference. See all Telegram error codes or the Telegram limits and quotas.

Related codes

Error 400 - quick answers

What does Telegram error 400 mean?

An inline keyboard button's callback_data does not meet the Bot API rule: 1 to 64 bytes. Exceeding 64 bytes, or sending an empty string, triggers this raw server error and rejects the whole message or edit. The limit is in bytes , so 64 characters of non-ASCII text can be far more than 64 bytes.

How do I fix Telegram error 400?

1. Measure len(callback_data.encode('utf-8')) for every button; keep it at or below 64. 2. Store state server-side and put only a short opaque key (for example a:123 ) in the button. 3. Use compact encodings (base64url of binary IDs) when you must carry more than one field. 4. Add a validation step in your keyboard builder that fails loudly in development. 5. If you edited an existing keyboard, note that every button in the new markup is validated, not only the one you…

Should I retry after error 400?

No. Retrying the same request produces the same error; the condition has to be fixed first. Treat it as a permanent failure for that message and surface it, rather than looping.

Stop debugging Telegram by hand

Connect the channel through Conferbot: tokens, webhooks and retries are handled, failures show as readable status.