{"record":{"id":"98bf987c2f914acb","repo":"agentscope-ai/agentscope","slug":"this-storage-backend-has-no-channel-support","errorCode":null,"errorMessage":"This storage backend has no channel support.","messagePattern":"This storage backend has no channel support\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"src/agentscope/app/storage/_base.py","lineNumber":641,"sourceCode":"        record: ChannelRecord,\n        platform_bot_id: str,\n    ) -> str:\n        \"\"\"Persist a channel record and refresh its indexes.\n\n        ``record.id`` is a globally unique UUID, so the record lives at a\n        single global key; ``record.user_id`` drives the per-user index\n        and ``platform_bot_id`` (extracted from credentials by the\n        caller) drives the uniqueness index.\n\n        Args:\n            record (`ChannelRecord`): The channel record to store.\n            platform_bot_id (`str`): The platform-side bot identifier,\n                used to maintain the dedup index.\n\n        Returns:\n            `str`: The id of the stored record.\n        \"\"\"\n        raise NotImplementedError(\n            \"This storage backend has no channel support.\",\n        )\n\n    async def get_channel(\n        self,\n        channel_id: str,\n    ) -> ChannelRecord | None:\n        \"\"\"Fetch a channel record by its global id.\n\n        This is the primary lookup, used both by the management API and\n        by the channel runtime (which only has a channel_id in hand).\n\n        Args:\n            channel_id (`str`): The channel id.\n\n        Returns:\n            `ChannelRecord | None`: The record, or ``None`` if not found.\n        \"\"\"","sourceCodeStart":623,"sourceCodeEnd":659,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/app/storage/_base.py#L623-L659","documentation":"StorageBase.upsert_channel is an optional part of the storage interface for channel (external platform) persistence. The base class raises NotImplementedError to signal that this backend does not support channels, so any caller that tries to persist a ChannelRecord through a non-channel-capable backend fails.","triggerScenarios":"Registering a bot/channel on a storage backend that only implements session/agent persistence, then calling storage.upsert_channel(...) directly or via a channel-service route (create or update channel).","commonSituations":"Plugging a custom or minimal StorageBase subclass into an app that uses channel features; using a memory/file backend in production where the channel router expects SQL-backed channel persistence; upgrading agentscope to a version that added channel APIs the backend hasn't implemented.","solutions":["Switch to a backend that implements channel support (e.g. AsyncSQLAlchemyStorage)","If writing a custom backend, override upsert_channel (and the other channel methods) in your StorageBase subclass","Disable/avoid channel features (channel routes, upsert flows) when using a channel-incapable backend"],"exampleFix":"# before\nstorage = MyMinimalStorage()\nawait storage.upsert_channel(record)  # NotImplementedError\n\n# after\nclass MyStorage(StorageBase):\n    async def upsert_channel(self, record, *, platform_bot_id=None) -> str:\n        # persist ChannelRecord and index platform_bot_id\n        ...\n        return record.channel_id","handlingStrategy":"type-guard","validationCode":"async def supports_channels(storage) -> bool:\n    return storage.upsert_channel.__func__ is not StorageBase.upsert_channel","typeGuard":"def has_channel_support(storage) -> TypeGuard[ChannelCapableStorage]:\n    return type(storage).upsert_channel is not StorageBase.upsert_channel","tryCatchPattern":"try:\n    await storage.upsert_channel(record)\nexcept NotImplementedError:\n    logger.warning(\"backend %s has no channel support; skipping\", type(storage).__name__)","preventionTips":["Advertise backend capabilities and gate channel routes on them","Prefer AsyncSQLAlchemyStorage for channel-enabled deployments","Cover all channel methods in custom backend integration tests"],"tags":["python","storage","not-implemented","channels","abstract-method"],"backgroundTag":"not-implemented-backend-capability","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}