python-telegram-bot/python-telegram-bot · error · ValueError
Message and chat_id pair are mutually exclusive
Error message
Message and chat_id pair are mutually exclusive
What it means
Application.migrate_chat_data() accepts either a `message` (a service message about migration) or the `old_chat_id`/`new_chat_id` pair — not both. Passing message together with either chat id raises ValueError.
Source
Thrown at src/telegram/ext/_application.py:1572
message (:class:`telegram.Message`, optional): A message with either
:attr:`~telegram.Message.migrate_from_chat_id` or
:attr:`~telegram.Message.migrate_to_chat_id`.
Mutually exclusive with passing :paramref:`old_chat_id` and
:paramref:`new_chat_id`.
.. seealso::
:attr:`telegram.ext.filters.StatusUpdate.MIGRATE`
old_chat_id (:obj:`int`, optional): The old chat ID.
Mutually exclusive with passing :paramref:`message`
new_chat_id (:obj:`int`, optional): The new chat ID.
Mutually exclusive with passing :paramref:`message`
Raises:
ValueError: Raised if the input is invalid.
"""
if message and (old_chat_id or new_chat_id):
raise ValueError("Message and chat_id pair are mutually exclusive")
if not any((message, old_chat_id, new_chat_id)):
raise ValueError("chat_id pair or message must be passed")
if message:
if message.migrate_from_chat_id is None and message.migrate_to_chat_id is None:
raise ValueError(
"Invalid message instance. The message must have either "
"`Message.migrate_from_chat_id` or `Message.migrate_to_chat_id`."
)
old_chat_id = message.migrate_from_chat_id or message.chat.id
new_chat_id = message.migrate_to_chat_id or message.chat.id
elif not (isinstance(old_chat_id, int) and isinstance(new_chat_id, int)):
raise ValueError("old_chat_id and new_chat_id must be integers")
self._chat_data[new_chat_id] = self._chat_data[old_chat_id]
self.drop_chat_data(old_chat_id)View on GitHub (pinned to d3b69d2e9f)
Solutions
- Pass only `message` and let the ids be extracted from it
- Or pass only the `old_chat_id`/`new_chat_id` pair without message
Example fix
# before await app.migrate_chat_data(message=msg, old_chat_id=old, new_chat_id=new) # after await app.migrate_chat_data(message=msg)
Defensive patterns
Strategy: validation
Validate before calling
if message and (old_chat_id or new_chat_id):
raise ValueError('pass either message or the id pair, not both') Prevention
- Pass either message or the id pair — never both
- Avoid blanket kwargs forwarding into migrate_chat_data
When it happens
Trigger: `app.migrate_chat_data(message=msg, old_chat_id=-100, new_chat_id=-200)`; also message plus only one of the ids triggers it because the check is `message and (old_chat_id or new_chat_id)`.
Common situations: Custom on_chat_migration logic copying docs and filling every parameter; generic wrapper code that passes all kwargs through.
Related errors
- chat_id pair or message must be passed
- Invalid message instance. The message must have either `Mess
- old_chat_id and new_chat_id must be integers
- The `year` argument is required if the `year` attribute was
- The parameter `inline_keyboard` should be a sequence of sequ
AI-assisted analysis of python-telegram-bot/python-telegram-bot@d3b69d2e9f (2026-08-28).
Data as JSON: /api/errors/30c199e5a41de9ee.
Report an issue: GitHub.