Skip to content

Interactive UI creates duplicate messages on button press instead of editing in-place #66

@zhou-zhichao

Description

@zhou-zhichao

Problem

When interacting with interactive UIs (AskUserQuestion, ExitPlanMode, Permission Prompt, etc.) via Telegram inline keyboard buttons, each button press (Up/Down/Enter/Space/Tab) creates a new message instead of editing the existing one. This results in multiple interactive UI messages accumulating in the topic.

Root Cause

In src/ccbot/handlers/interactive_ui.py, the handle_interactive_ui function (line ~193-210) tries to edit the existing message, but catches all exceptions and falls through to sending a new message:

existing_msg_id = _interactive_msgs.get(ikey)
if existing_msg_id:
    try:
        await bot.edit_message_text(...)
        return True
    except Exception:
        # Edit failed — clears msg_id but does NOT delete the old message
        _interactive_msgs.pop(ikey, None)
        # Falls through to send a NEW message

Two issues here:

  1. "Message is not modified" error: When the terminal content hasn't changed after a button press, Telegram raises BadRequest: Message is not modified. The broad except Exception catches this and creates a duplicate message unnecessarily.

  2. Old message not deleted on other failures: When the edit genuinely fails (message deleted externally, etc.), the old message is not deleted before sending a new one, leaving a stale UI message in the chat.

Suggested Fix

existing_msg_id = _interactive_msgs.get(ikey)
if existing_msg_id:
    try:
        await bot.edit_message_text(...)
        _interactive_mode[ikey] = window_id
        return True
    except BadRequest as e:
        if "Message is not modified" in str(e):
            # Content unchanged — keep existing message, no action needed
            _interactive_mode[ikey] = window_id
            return True
        # Other edit failure — delete old message before sending new
        logger.debug("Edit failed for interactive msg %s: %s, sending new", existing_msg_id, e)
        _interactive_msgs.pop(ikey, None)
        try:
            await bot.delete_message(chat_id=chat_id, message_id=existing_msg_id)
        except Exception:
            pass
    except Exception:
        logger.debug("Edit failed for interactive msg %s, sending new", existing_msg_id)
        _interactive_msgs.pop(ikey, None)
        try:
            await bot.delete_message(chat_id=chat_id, message_id=existing_msg_id)
        except Exception:
            pass

This ensures only one interactive UI message exists at any time.

Expected Behavior

  • Button presses should edit the existing interactive UI message in-place
  • If content hasn't changed, keep the existing message (no duplicate)
  • If edit fails for other reasons, delete the old message before sending a new one
  • There should always be at most one interactive UI message per topic

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions