{"record":{"id":"1b6907657052629f","repo":"HKUDS/nanobot","slug":"channel-plugin-webui-entry-must-stay-inside-its-pa","errorCode":null,"errorMessage":"channel plugin webui entry must stay inside its package","messagePattern":"channel plugin webui entry must stay inside its package","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"nanobot/channels/plugin.py","lineNumber":71,"sourceCode":"            raise TypeError(\"channel plugin setup must be a ChannelSetupSpec or None\")\n        if not isinstance(cast(object, self.management), ChannelManagementSpec):\n            raise TypeError(\"channel plugin management must be a ChannelManagementSpec\")\n        if not isinstance(cast(object, self.dependencies), tuple) or not all(\n            isinstance(cast(object, requirement), str) and requirement.strip()\n            for requirement in self.dependencies\n        ):\n            raise TypeError(\"channel plugin dependencies must be a tuple of requirements\")\n        for dependency in self.dependencies:\n            try:\n                Requirement(dependency)\n            except InvalidRequirement as exc:\n                raise ValueError(\n                    f\"channel plugin dependency is not a valid requirement: {dependency}\"\n                ) from exc\n        if self.webui is not None:\n            webui = self.webui.replace(\"\\\\\", \"/\")\n            if webui.startswith(\"/\") or \"..\" in webui.split(\"/\"):\n                raise ValueError(\"channel plugin webui entry must stay inside its package\")\n            object.__setattr__(self, \"webui\", webui)\n\n    def load_channel_class(self) -> type[BaseChannel]:\n        \"\"\"Resolve and validate the runtime class only when the channel is needed.\"\"\"\n        from nanobot.channels.base import BaseChannel\n\n        module_name, _, attr_name = self.runtime.partition(\":\")\n        module = importlib.import_module(module_name)\n        channel_cls: Any = getattr(module, attr_name, None)\n        if (\n            not isinstance(channel_cls, type)\n            or not issubclass(channel_cls, BaseChannel)\n            or channel_cls is BaseChannel\n        ):\n            raise ImportError(\n                f\"Channel plugin '{self.name}' runtime '{self.runtime}' \"\n                \"does not resolve to a BaseChannel subclass\"\n            )","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/HKUDS/nanobot/blob/42f37dc4c0e409eac7818a82d165c5f2757bc075/nanobot/channels/plugin.py#L53-L89","documentation":"Error \"channel plugin webui entry must stay inside its package\" thrown in HKUDS/nanobot.","triggerScenarios":"Thrown at nanobot/channels/plugin.py:71 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"42f37dc4c0e409eac7818a82d165c5f2757bc075","analyzedAt":"2026-08-26T00:18:52.276Z","schemaVersion":2},"datasetVersion":"2026-08-26T04:18:47.238Z"}