{"record":{"id":"80d508fe44006bd3","repo":"python-telegram-bot/python-telegram-bot","slug":"callback-data-must-be-a-tuple-of-length-2","errorCode":null,"errorMessage":"callback_data must be a tuple of length 2","messagePattern":"callback_data must be a tuple of length 2","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/telegram/ext/_application.py","lineNumber":581,"sourceCode":"            self._user_data.update(await self.persistence.get_user_data())\n        if self.persistence.store_data.chat_data:\n            self._chat_data.update(await self.persistence.get_chat_data())\n        if self.persistence.store_data.bot_data:\n            self.bot_data = await self.persistence.get_bot_data()\n            if not isinstance(self.bot_data, self.context_types.bot_data):\n                raise ValueError(\n                    f\"bot_data must be of type {self.context_types.bot_data.__name__}\"\n                )\n\n        # Mypy doesn't know that persistence.set_bot (see above) already checks that\n        # self.bot is an instance of ExtBot if callback_data should be stored ...\n        if self.persistence.store_data.callback_data and (\n            self.bot.callback_data_cache is not None  # type: ignore[attr-defined]\n        ):\n            persistent_data = await self.persistence.get_callback_data()\n            if persistent_data is not None:\n                if not isinstance(persistent_data, tuple) or len(persistent_data) != 2:\n                    raise ValueError(\"callback_data must be a tuple of length 2\")\n                self.bot.callback_data_cache.load_persistence_data(  # type: ignore[attr-defined]\n                    persistent_data\n                )\n\n    async def start(self) -> None:\n        \"\"\"Starts\n\n        * a background task that fetches updates from :attr:`update_queue` and processes them via\n          :meth:`process_update`.\n        * :attr:`job_queue`, if set.\n        * a background task that calls :meth:`update_persistence` in regular intervals, if\n          :attr:`persistence` is set.\n\n        Note:\n            This does *not* start fetching updates from Telegram. To fetch updates, you need to\n            either start :attr:`updater` manually or use one of :meth:`run_polling` or\n            :meth:`run_webhook`.\n","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/python-telegram-bot/python-telegram-bot/blob/d3b69d2e9fb7af6c796f84516cfda751752c7cb7/src/telegram/ext/_application.py#L563-L599","documentation":"When persistence stores callback_data and the bot has a callback_data_cache, initialize() loads the persisted callback data, which must be a tuple of length 2 (the persisted callback_data and keyboard_data of the CallbackDataCache). If the persistence layer returns anything other than a 2-tuple, a ValueError is raised.","triggerScenarios":"A custom persistence implementation whose get_callback_data returns a list, a dict, or a tuple with != 2 elements; corrupted or manually edited persistence files from a prior version.","commonSituations":"Writing a custom database-backed persistence and misunderstanding the expected format; pickle files created by an older telegram.ext version with a different structure.","solutions":["Return a tuple `(callback_data, keyboard_data)` of length 2 from get_callback_data, matching what CallbackDataCache.persistence_data yields","Delete/migrate stale persisted callback data created by older versions"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"cd = await persistence.get_callback_data()\nassert cd is None or (isinstance(cd, tuple) and len(cd) == 2)","typeGuard":"def is_valid_callback_data(cd) -> bool:\n    return cd is None or (isinstance(cd, tuple) and len(cd) == 2)","tryCatchPattern":null,"preventionTips":["Implement get_callback_data to echo CallbackDataCache.persistence_data structure","Test persistence round-trips after upgrades","Discard incompatible persisted callback data instead of loading it"],"tags":["persistence","callback-data","validation"],"backgroundTag":"persistence-schema-mismatch","analyzedSha":"d3b69d2e9fb7af6c796f84516cfda751752c7cb7","analyzedAt":"2026-08-28T16:18:54.805Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}