Why is callback_query_handler in telebot not working?
Here’s the inline call:
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 the decorator which for some reason doesn’t work (even a simple print(1) doesn’t show):
@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)
Problems with callback_query_handler in telebot usually occur due to incorrect handler registration, conflicts with other handlers, or errors in the function signature. Your decorator code looks syntactically correct, but there are several common issues that can cause this behavior.
Table of Contents
- Main reasons for non-working callback_query_handler
- Checking handler registration
- Analyzing your code and errors
- Solving the problem
- Additional checks
- Working code example
- Sources
Main reasons for non-working callback_query_handler
Callback_query_handler in telebot may not work for several reasons:
- Incorrect handler registration - the handler might be registered after polling has started
- Conflicts with other handlers - other handlers might intercept callback requests
- Errors in function signature - the handler function must accept the correct parameters
- Problems with answering callback - unanswered callback queries can cause issues
- Library version - some versions of pyTelegramBotAPI have known bugs
As noted in the pyTelegramBotAPI documentation, callback queries require proper handling and response.
Checking handler registration
Ensure your callback_query_handler is registered before starting polling:
# Register the handler BEFORE starting polling
@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, 'List of anomalies: ...')
elif callback.data == 'show_empl':
bot.send_message(callback.message.chat.id, 'List of employees: ...')
elif callback.data == 'show_items':
bot.send_message(callback.message.chat.id, 'List of items: ...')
bot.answer_callback_query(callback.id)
# Start polling AFTER registering all handlers
bot.polling(none_stop=True)
As explained on Stack Overflow, handlers must be registered in the correct order.
Analyzing your code and errors
There are several critical errors in your code:
- Non-existent variable
message:
# WRONG - variable message is not defined
bot.send_message(message.chat.id, f'List of anomalies: ...')
# CORRECT - use callback.message
bot.send_message(callback.message.chat.id, f'List of anomalies: ...')
- Missing error handling - add try-except for debugging:
@bot.callback_query_handler(func=lambda callback: True)
def callback_query_handler(callback):
try:
print(f"Callback received: {callback.data}")
# your code
except Exception as e:
print(f"Error in callback_handler: {e}")
As shown in the GitHub example, proper use of callback queries includes error handling.
Solving the problem
Here’s a corrected version of your code:
@bot.callback_query_handler(func=lambda callback: True)
def callback_query_handler(callback):
try:
print(1) # Check if the handler is being called
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: ...')
# Always answer the callback to remove the "clock"
bot.answer_callback_query(callback.id, text="Processing...")
except Exception as e:
print(f"Error in callback_handler: {e}")
bot.answer_callback_query(callback.id, text="Error!")
Also ensure your handler is properly registered and there are no conflicts with other handlers.
Additional checks
- Check the library version:
import telebot
print(telebot.__version__)
- Add logging to track callback requests:
import logging
# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@bot.callback_query_handler(func=lambda callback: True)
def callback_query_handler(callback):
logger.info(f"Callback received: {callback.data} from {callback.from_user.id}")
# rest of the code
- Check for handler conflicts - ensure you don’t have other handlers that might intercept callback requests.
As noted in the GitHub discussion, proper handler configuration is important for correct inline button functionality.
Working code example
Here’s a complete working example with callback_query_handler:
import telebot
from telebot import types
import json
bot = telebot.TeleBot('YOUR_TOKEN_HERE')
@bot.message_handler(commands=['start'])
def start_command(message):
# Create 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"))
bot.send_message(message.chat.id, 'Inventory:', reply_markup=keyboard)
@bot.callback_query_handler(func=lambda callback: True)
def callback_query_handler(callback):
try:
print(f"Callback received: {callback.data}")
if callback.data == 'show_anom':
bot.send_message(callback.message.chat.id, 'List of anomalies: ...')
elif callback.data == 'show_empl':
bot.send_message(callback.message.chat.id, 'List of employees: ...')
elif callback.data == 'show_items':
bot.send_message(callback.message.chat.id, 'List of items: ...')
# Answer the callback to remove the loading indicator
bot.answer_callback_query(callback.id, text="Processing complete")
except Exception as e:
print(f"Error in callback_handler: {e}")
bot.answer_callback_query(callback.id, text="An error occurred")
# Start the bot
bot.polling(none_stop=True)
Sources
- Official pyTelegramBotAPI Documentation - CallbackQuery
- Stack Overflow - Why is my Telegram Bot callback query handler not working?
- GitHub Discussion - Callback query handler don’t work
- GitHub Issue - How we should set callback query handler for inline buttons?
- Stack Overflow - PyTelegrambotApi — @callback_query_handler does not work
Conclusion
The main issues with callback_query_handler in telebot are typically related to:
- Incorrect variable usage - always use
callback.messageinstead ofmessage - Missing callback response - always call
bot.answer_callback_query() - Incorrect handler registration - register all handlers before starting polling
- Missing error handling - add try-except blocks for debugging
After fixing these issues, your callback_query_handler should work correctly. If the problem persists, check your library version and add detailed logging for debugging.