Skip to content

fix(bots): avoid Telegram 64-byte callback_data overflow on bots menu#61

Open
gordonkoehn wants to merge 2 commits into
hummingbot:mainfrom
gordonkoehn:fix/bot-name-callback-overflow
Open

fix(bots): avoid Telegram 64-byte callback_data overflow on bots menu#61
gordonkoehn wants to merge 2 commits into
hummingbot:mainfrom
gordonkoehn:fix/bot-name-callback-overflow

Conversation

@gordonkoehn
Copy link
Copy Markdown

Problem

/bots fails with telegram.error.BadRequest: Button_data_invalid when any bot has a name long enough that bots:bot_detail:{bot_name} exceeds Telegram's 64-byte callback_data cap (16-byte prefix + name, so names ≥ 49 chars overflow).

Reproduction

Deploy any bot whose instance_name is ≥ 49 chars. This happens unprompted with the Hummingbot Backend API's deploy-v2-controllers endpoint, which appends its own deploy-time timestamp to whatever instance_name you supply — long names are the default, not the exception. Observed on a fresh install:

pmm-DOLO-USDC-binance-v6-20260419-120000-20260419-120000-20260419-125551   (72 chars)

callback_data = 88 bytes → menu never renders. Log:

handlers.bots.menu - ERROR - Error showing bots menu: Button_data_invalid
telegram.error.BadRequest: Button_data_invalid

Fix

Switch _build_main_menu_keyboard to emit callback_data=f"bots:bot_idx:{i}" and stash the ordered bot-name list in context.chat_data["bots_main_list"] when the menu is built. A new dispatcher branch resolves bot_idx back to the bot_name and calls show_bot_detail().

  • handlers/bots/menu.py: index-based callback + chat_data cache
  • handlers/bots/__init__.py: new bot_idx branch next to existing bot_detail

Legacy bots:bot_detail:{name} branch is retained for callers that pass known-short names. Pattern mirrors the existing ctrl_idx mechanism already in the same dispatcher.

Scope

  • Two files, +44 / −6 lines net.
  • No behavioral change for bots with short names.
  • No new dependencies.
  • Resilient to cache miss: if bots_main_list is absent or the index is out of range (e.g. stale button after a restart), logs a warning and re-opens the bots menu instead of crashing.

Validated end-to-end

Tested against a live bot deployed via POST /bot-orchestration/deploy-v2-controllers (72-char name, 88-byte callback_data). Stock upstream image crashes with Button_data_invalid; this branch renders the menu cleanly and both /bots and the bot-detail drill-down return HTTP 200. Postmortem: gordonkoehn/riskcraft#164.

Long bot_names (e.g. hummingbot-deploy's
'pmm-EPIC-USDT-kucoin-v1-<ts>-<ts>' format, 54 chars) plus the
'bots:bot_detail:' prefix (16 bytes) exceed Telegram's 64-byte
InlineKeyboardButton.callback_data cap, producing
telegram.error.BadRequest: Button_data_invalid and rendering /bots
unusable.

Switch the main bots menu to index-based callback_data
(bots:bot_idx:{i}), stashing the ordered bot-name list in
context.chat_data['bots_main_list'] when the menu is built. A new
dispatcher branch resolves the index back to the name and calls
show_bot_detail(). Legacy bots:bot_detail:{name} branch retained for
callers that pass known-short names.

Pattern mirrors the existing ctrl_idx mechanism in the same dispatcher.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes /bots rendering failures caused by Telegram’s 64-byte InlineKeyboardButton.callback_data limit by switching the bots-menu callbacks to an index-based scheme and resolving indices back to bot names via cached state.

Changes:

  • Updated the bots main menu keyboard to use bots:bot_idx:{i} callback data instead of embedding bot_name.
  • Cached the ordered bot list in context state when building the menu so indices can be resolved later.
  • Added a new bot_idx callback branch in the bots dispatcher while retaining the legacy bot_detail branch.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
handlers/bots/menu.py Emits index-based callbacks for bot buttons and caches the ordered bot-name list used for resolution.
handlers/bots/init.py Adds dispatcher support for bot_idx callbacks, resolving indices back to bot names and handling stale/missing cache cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread handlers/bots/__init__.py Outdated
Comment thread handlers/bots/menu.py
Comment thread handlers/bots/menu.py Outdated
… import

Addresses three Copilot review comments on hummingbot#61:

1. Use context.user_data (not chat_data) for the cached bot-name list so
   group-chat users don't overwrite each other's state. Matches the
   per-user convention used elsewhere in this handler.

2. Prefer the stable name-based callback_data form when it fits the
   64-byte cap, fall back to index-based only when the name would
   overflow. Short-named bots keep the original upstream behavior:
   buttons on stale menu messages stay correct across list reordering.
   Only long-named bots (>= 49 chars) use the index-based form, where
   list stability is a hard trade-off vs not crashing.

3. Drop the redundant local re-import of show_bots_menu inside the
   bot_idx dispatcher branch — already imported at module scope.

Validated end-to-end: same 72-char bot name exercises the index path
cleanly.
@gordonkoehn
Copy link
Copy Markdown
Author

gordonkoehn commented Apr 19, 2026

Addressed all three in 384c7f2:

  1. chat_datauser_data for bots_main_list cache, per your group-chat concern. Matches the per-user convention in this handler.
  2. Hybrid callback_data: prefer the stable name-based form bots:bot_detail:{name} when it fits the 64-byte cap; fall back to index-based bots:bot_idx:{i} only when the name would overflow. Short-named bots keep the original upstream behavior (stable across stale menu messages, list-reorder safe). Only long-named bots (≥ 49 chars) accept the index trade-off.
  3. Dropped the redundant local from handlers.bots.menu import show_bots_menu — already imported at module scope.

Re-validated the fix end-to-end with the same 72-char bot name after the revision; /bots + button-tap both return HTTP 200 cleanly. Postmortem of the first validation round is in gordonkoehn/riskcraft#164.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants