NeuroAgent

Why callback_query_handler in telebot is not working

Fix callback_query_handler issues in telebot. Learn about common errors and proper implementation of inline buttons with callback_data.

Question

Why isn’t the callback_query_handler working in the telebot library? I created an inline keyboard with buttons that have callback_data, but the callback query handler isn’t triggering. Here’s the code for creating the inline keyboard:

python
keyboard = InlineKeyboardMarkup()
keyboard.add(InlineKeyboardButton(text='Show anomalies', callback_data="show_anom"))
keyboard.add(InlineKeyboardButton(text='Show employees', callback_data="show_empl"))
keyboard.add(InlineKeyboardButton(text='Show items', callback_data="show_items"))
bot.send_message(message.from_user.id, f'Inventory: \nNumber of anomalies: {str(len(json.loads(log_info(message, 4))))}\nNumber of employees: {str(len(json.loads(log_info(message, 3))))}\nNumber of equipment: {str(len(json.loads(log_info(message, 5))))}', reply_markup=keyboard)
bot.delete_message(message.chat.id, message.message_id)

And here’s my callback query handler, which for some reason isn’t working (even a simple print(1) doesn’t execute):

python
@bot.callback_query_handler(func=lambda callback: True)
def callback_query_handler(callback):
    print(1)
    message: Message
    if callback.data == 'show_anom':
        bot.send_message(message.chat.id, f'List of anomalies: ...')
    elif callback.data == 'show_empl':
        bot.send_message(message.chat.id, f'List of employees: ...')
    elif callback.data == 'show_items':
        bot.send_message(message.chat.id, f'List of items: ...')
    bot.answer_callback_query(callback.id)

What could be the problem and how do I properly configure callback query handling in telebot?

NeuroAgent

Your code contains several common errors that lead to the callback_query_handler not working. The main problem is in the callback query handler - you’re using an undefined variable message, and you’ve also made other errors in the code structure.

Contents

Main problem in the code

The main error in your handler is using the variable message, which is not defined inside the callback_query_handler function. Instead, you should use the callback object, which contains all the information about the callback query, including callback.message.chat.id.

python
# WRONG (your code)
bot.send_message(message.chat.id, f'List of anomalies: ...')

# CORRECT
bot.send_message(callback.message.chat.id, f'List of anomalies: ...')

Correct implementation of callback_query_handler

Here’s how the corrected callback query handler should look:

python
@bot.callback_query_handler(func=lambda callback: True)
def callback_query_handler(callback):
    print(1)  # This should now work
    if callback.data == 'show_anom':
        bot.send_message(callback.message.chat.id, f'List of anomalies: ...')
    elif callback.data == 'show_empl':
        bot.send_message(callback.message.chat.id, f'List of employees: ...')
    elif callback.data == 'show_items':
        bot.send_message(callback.message.chat.id, f'List of items: ...')
    bot.answer_callback_query(callback.id)

Complete corrected code

python
from telebot import types

# Creating inline keyboard
keyboard = types.InlineKeyboardMarkup()
keyboard.add(types.InlineKeyboardButton(text='Show anomalies', callback_data="show_anom"))
keyboard.add(types.InlineKeyboardButton(text='Show employees', callback_data="show_empl"))
keyboard.add(types.InlineKeyboardButton(text='Show items', callback_data="show_items"))

# Sending message with keyboard
bot.send_message(message.from_user.id, 
    f'Inventory: \nNumber of anomalies: {str(len(json.loads(log_info(message, 4))))}\n'
    f'Number of employees: {str(len(json.loads(log_info(message, 3))))}\n'
    f'Number of equipment: {str(len(json.loads(log_info(message, 5))))}', 
    reply_markup=keyboard
)

# Deleting previous message
bot.delete_message(message.chat.id, message.message_id)

# Callback query handler
@bot.callback_query_handler(func=lambda callback: True)
def callback_query_handler(callback):
    print(1)  # For debugging
    if callback.data == 'show_anom':
        bot.send_message(callback.message.chat.id, f'List of anomalies: ...')
    elif callback.data == 'show_empl':
        bot.send_message(callback.message.chat.id, f'List of employees: ...')
    elif callback.data == 'show_items':
        bot.send_message(callback.message.chat.id, f'List of items: ...')
    bot.answer_callback_query(callback.id)

Additional possible causes of malfunction

If after fixing the main problem the handler still doesn’t work, check the following points:

  1. Import types: Make sure you’ve correctly imported types from telebot:

    python
    from telebot import types
    
  2. Bot initialization: Check that your bot is running using bot.polling():

    python
    if __name__ == '__main__':
        bot.polling(none_stop=True)
    
  3. Handler conflicts: Make sure there are no other handlers that might be intercepting callback queries.

  4. Bot permissions: Check that the bot has the necessary permissions to send messages and delete messages in the chat.

  5. Library version: Make sure you’re using an up-to-date version of telebot. Version 0.0.4 or later is recommended.

Debugging recommendations

For diagnosing the problem, add more debugging information:

python
@bot.callback_query_handler(func=lambda callback: True)
def callback_query_handler(callback):
    print(f"Callback received! Data: {callback.data}")
    print(f"Chat ID: {callback.message.chat.id}")
    print(f"Message ID: {callback.message.message_id}")
    
    try:
        if callback.data == 'show_anom':
            bot.send_message(callback.message.chat.id, f'List of anomalies: ...')
        elif callback.data == 'show_empl':
            bot.send_message(callback.message.chat.id, f'List of employees: ...')
        elif callback.data == 'show_items':
            bot.send_message(callback.message.chat.id, f'List of items: ...')
        bot.answer_callback_query(callback.id)
    except Exception as e:
        print(f"Error in handler: {e}")
        bot.answer_callback_query(callback.id, "An error occurred")

Best practices when working with inline keyboards

  1. Use static callback_data: For simple cases, it’s better to use static strings in callback_data, as you’re doing.

  2. Handle all callback queries: Always use bot.answer_callback_query() to respond to the callback to remove the “clocks” from the button.

  3. Delete messages when necessary: As in your code, deleting the old message with the keyboard is a good practice.

  4. Handle errors: Add exception handling to your callback handler.

  5. Use message editing: Instead of sending a new message, you can edit the existing one:

    python
    bot.edit_message_text(text='New message', chat_id=callback.message.chat.id, message_id=callback.message.message_id)
    

After fixing the main problem (using callback.message.chat.id instead of message.chat.id), your code should start working correctly.