python-telegram-bot/python-telegram-bot · error · ValueError
You can not filter for users and include anonymous reactions
Error message
You can not filter for users and include anonymous reactions. Set `message_reaction_types` to MESSAGE_REACTION_UPDATED.
What it means
MessageReactionHandler can filter by users, but anonymous reactions ( MESSAGE_REACTION and MESSAGE_REACTION_COUNT_UPDATED reaction types) have no user attached. Filtering by user_id/user_username while including those anonymous reaction types is contradictory, so __init__ raises ValueError immediately.
Source
Thrown at src/telegram/ext/_handlers/messagereactionhandler.py:131
self: "MessageReactionHandler[CCT, RT]",
callback: HandlerCallback[Update, CCT, RT],
chat_id: SCT[int] | None = None,
chat_username: SCT[str] | None = None,
user_id: SCT[int] | None = None,
user_username: SCT[str] | None = None,
message_reaction_types: int = MESSAGE_REACTION,
block: DVType[bool] = DEFAULT_TRUE,
):
super().__init__(callback, block=block)
self.message_reaction_types: int = message_reaction_types
self._chat_ids = parse_chat_id(chat_id)
self._chat_usernames = parse_username(chat_username)
if (user_id or user_username) and message_reaction_types in (
self.MESSAGE_REACTION,
self.MESSAGE_REACTION_COUNT_UPDATED,
):
raise ValueError(
"You can not filter for users and include anonymous reactions. Set "
"`message_reaction_types` to MESSAGE_REACTION_UPDATED."
)
self._user_ids = parse_chat_id(user_id)
self._user_usernames = parse_username(user_username)
def check_update(self, update: object) -> bool:
"""Determines whether an update should be passed to this handler's :attr:`callback`.
Args:
update (:class:`telegram.Update` | :obj:`object`): Incoming update.
Returns:
:obj:`bool`
"""
if not isinstance(update, Update):
return FalseView on GitHub (pinned to d3b69d2e9f)
Solutions
- Set message_reaction_types to MessageReactionHandler.MESSAGE_REACTION_UPDATED (the non-anonymous type) when filtering by user
- Or drop the user_id/user_username arguments to keep anonymous reactions
- If you need both, register two handlers: one user-filtered for MESSAGE_REACTION_UPDATED and one unfiltered for anonymous types
Example fix
# before
MessageReactionHandler(
callback,
user_id=12345,
message_reaction_types=MessageReactionHandler.ALL_TYPES,
)
# after
MessageReactionHandler(
callback,
user_id=12345,
message_reaction_types=MessageReactionHandler.MESSAGE_REACTION_UPDATED,
) Defensive patterns
Strategy: validation
Validate before calling
from telegram.ext import MessageReactionHandler
anonymous = (MessageReactionHandler.MESSAGE_REACTION, MessageReactionHandler.MESSAGE_REACTION_COUNT_UPDATED)
def is_valid(user_id, user_username, types):
has_user = bool(user_id or user_username)
included = types in anonymous or (isinstance(types, (list, tuple, set)) and any(t in anonymous for t in types))
return not (has_user and included) Prevention
- Remember anonymous reactions have no user by definition
- Construct handlers in a helper that enforces the user/anonymous-type exclusion
When it happens
Trigger: MessageReactionHandler(user_id=..., user_username=..., message_reaction_types=MessageReactionHandler.MESSAGE_REACTION) — or MESSAGE_REACTION_COUNT_UPDATED — or an iterable containing them. Any user filter combined with anonymous reaction types raises at construction time.
Common situations: Wanting to track all reactions including anonymous ones while also restricting to a specific user. Developers often pass message_reaction_types=MessageReactionHandler.ALL_TYPES together with user_id, which includes the anonymous types.
Related errors
- callback_data_json is not in the required format
- Unable to deserialize conversations_json. Not valid JSON
- `rate_limit_args` can only be used if a `ExtBot.rate_limiter
- The `pattern` must not be a coroutine function! Use an ordin
- Command `{comm}` is not a valid bot command
AI-assisted analysis of python-telegram-bot/python-telegram-bot@d3b69d2e9f (2026-08-28).
Data as JSON: /api/errors/498f8421c41a159f.
Report an issue: GitHub.