{"record":{"id":"00c3d83d6ba572ed","repo":"agentscope-ai/agentscope","slug":"channel-cls-name-must-set-a-non-empty-chann","errorCode":null,"errorMessage":"{channel_cls.__name__} must set a non-empty 'channel_type' to be registered.","messagePattern":"(.+?) must set a non-empty 'channel_type' to be registered\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/agentscope/app/channel/_registry.py","lineNumber":68,"sourceCode":"                ``create_app(channels=[...])``.\n        \"\"\"\n        self._classes: dict[str, type[\"ChannelBase\"]] = {}\n        for channel_cls in channels or []:\n            self.register(channel_cls)\n\n    def __bool__(self) -> bool:\n        \"\"\"Whether any channel type is registered (feature enabled).\"\"\"\n        return bool(self._classes)\n\n    def register(self, channel_cls: type[\"ChannelBase\"]) -> None:\n        \"\"\"Register a channel class under its ``channel_type``.\n\n        Args:\n            channel_cls (`type[ChannelBase]`): The channel class to add.\n        \"\"\"\n        channel_type = channel_cls.channel_type\n        if not channel_type:\n            raise ValueError(\n                f\"{channel_cls.__name__} must set a non-empty \"\n                f\"'channel_type' to be registered.\",\n            )\n        self._classes[channel_type] = channel_cls\n\n    def get(self, channel_type: str) -> type[\"ChannelBase\"] | None:\n        \"\"\"Return the channel class for a type, or ``None``.\n\n        Args:\n            channel_type (`str`): The platform type id.\n        \"\"\"\n        return self._classes.get(channel_type)\n\n    def has_type(self, channel_type: str) -> bool:\n        \"\"\"Whether a type is registered.\n\n        Args:\n            channel_type (`str`): The platform type id.","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/app/channel/_registry.py#L50-L86","documentation":"ValueError raised by ChannelRegistry.register when a ChannelBase subclass has an empty/None channel_type class attribute. The registry keys channel classes by channel_type, so a blank type would make the channel unreachable (or silently collide with other empty keys); registration therefore fails fast at app creation time.","triggerScenarios":"Calling create_app(channels=[MyChannel]) where MyChannel subclasses ChannelBase but does not define channel_type (or sets it to \"\" or None). The registry's __init__ registers each provided class, so the error surfaces during create_app.","commonSituations":"Writing a custom channel and forgetting the channel_type attribute, overriding class attributes in __init_subclass__ and blanking channel_type, copy-pasting a channel stub without filling in required class fields.","solutions":["Add a unique non-empty channel_type class attribute to your channel subclass (e.g. channel_type = \"mychat\")","Check you didn't shadow channel_type with an instance attribute or a None default","Ensure any base-class default is not being set to empty string in intermediate subclasses"],"exampleFix":"# before\nclass MyChannel(ChannelBase):\n    # channel_type missing\n    ...\n\n# after\nclass MyChannel(ChannelBase):\n    channel_type = \"mychat\"\n    ...","handlingStrategy":"type-guard","validationCode":"def is_registerable_channel(cls) -> bool:\n    return isinstance(cls, type) and issubclass(cls, ChannelBase) and bool(getattr(cls, \"channel_type\", None))","typeGuard":"def assert_valid_channel(cls: type[ChannelBase]) -> None:\n    if not getattr(cls, \"channel_type\", None):\n        raise TypeError(f\"{cls.__name__} must define a non-empty channel_type\")","tryCatchPattern":"try:\n    app = create_app(channels=[MyChannel])\nexcept ValueError as e:\n    if \"channel_type\" in str(e):\n        fix_and_define_channel_type()  # add class attribute and recreate app","preventionTips":["Define channel_type immediately when subclassing ChannelBase","Add a unit test that registers all your channel classes to catch blanks early"],"tags":["channel","registry","custom-channel","validation"],"backgroundTag":"registry-missing-type-key","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}