{"record":{"id":"a6536dda0db1bd30","repo":"sansan0/TrendRadar","slug":"invalid-parameter-a6536d","errorCode":"INVALID_PARAMETER","errorMessage":"无效的渠道: {invalid}","messagePattern":"无效的渠道: (.+?)","errorType":"error_code","errorClass":"InvalidParameterError","httpStatus":null,"severity":"error","filePath":"mcp_server/tools/notification.py","lineNumber":1149,"sourceCode":"                \"error\": {\"code\": \"EMPTY_MESSAGE\", \"message\": \"消息内容不能为空\"},\n            }\n\n        try:\n            config = self._load_merged_config()\n\n            if not config.get(\"ENABLE_NOTIFICATION\", True):\n                return {\n                    \"success\": False,\n                    \"error\": {\"code\": \"NOTIFICATION_DISABLED\", \"message\": \"通知功能已禁用（notification.enabled = false）\"},\n                }\n\n            # 确定目标渠道\n            all_channel_ids = list(_CHANNEL_REQUIREMENTS.keys())\n            if channels:\n                # 验证渠道名称\n                invalid = [ch for ch in channels if ch not in all_channel_ids]\n                if invalid:\n                    raise InvalidParameterError(\n                        f\"无效的渠道: {invalid}\",\n                        suggestion=f\"支持的渠道: {all_channel_ids}\"\n                    )\n                target_channels = channels\n            else:\n                # 发送到所有已配置渠道\n                target_channels = [\n                    ch_id for ch_id, keys in _CHANNEL_REQUIREMENTS.items()\n                    if all(config.get(k) for k in keys)\n                ]\n\n            if not target_channels:\n                return {\n                    \"success\": False,\n                    \"error\": {\n                        \"code\": \"NO_CHANNELS\",\n                        \"message\": \"没有已配置的目标渠道\",\n                        \"suggestion\": \"请在 config.yaml 或 .env 中配置至少一个通知渠道\",","sourceCodeStart":1131,"sourceCodeEnd":1167,"githubUrl":"https://github.com/sansan0/TrendRadar/blob/8ee26026ba6c11dec41a95fb3895a7162876caa1/mcp_server/tools/notification.py#L1131-L1167","documentation":"Thrown by the notification tool when the caller passes channel names that are not keys of the internal _CHANNEL_REQUIREMENTS registry. The tool first checks config ENABLE_NOTIFICATION, then validates every entry in the `channels` argument against the known channel ids before dispatching. Any unknown string in the list aborts the whole send.","triggerScenarios":"Calling the send-notification MCP tool with channels=[\"sms\"] when only ids in _CHANNEL_REQUIREMENTS exist (e.g. wechat_work, dingtalk, feishu, email); passing an empty-string or misspelled channel id; passing channels when no matching credentials are configured for that id.","commonSituations":"Typos in channel names (\"dingding\" vs \"dingtalk\"); assuming a channel is supported because credentials are configured; channel sets differing between deployments/versions of the server.","solutions":["Use only channel ids listed in the error's suggestion field (it prints the full _CHANNEL_REQUIREMENTS key list)","If you want every configured channel, omit the `channels` argument entirely — the tool auto-selects channels whose required config keys are all set","Verify the channel's required credential keys exist in config before naming it explicitly"],"exampleFix":"# before\nsend_notification(content=\"deploy done\", channels=[\"dingding\"])\n\n# after\nsend_notification(content=\"deploy done\", channels=[\"dingtalk\"])\n# or send to all configured channels:\nsend_notification(content=\"deploy done\")","handlingStrategy":"validation","validationCode":"VALID_CHANNELS = {\"wechat_work\", \"dingtalk\", \"feishu\", \"email\"}  # keep in sync with server _CHANNEL_REQUIREMENTS\n\ndef pick_channels(requested):\n    if not requested:\n        return None  # let server auto-select configured channels\n    bad = [c for c in requested if c not in VALID_CHANNELS]\n    if bad:\n        raise ValueError(f\"unknown channels {bad}; valid: {sorted(VALID_CHANNELS)}\")\n    return requested","typeGuard":"def is_channel_list(v) -> bool:\n    return v is None or (isinstance(v, list) and all(isinstance(c, str) for c in v))","tryCatchPattern":"try:\n    send_notification(content, channels=ch)\nexcept InvalidParameterError as e:\n    if \"无效的渠道\" in str(e):\n        # parse suggestion list from error and retry with corrected channels, or send without `channels`\n        send_notification(content)\n    else:\n        raise","preventionTips":["Source the valid channel list from the server's documented schema instead of hardcoding guesses","Omit `channels` to auto-target every fully-configured channel","Log the error's suggestion field once and cache the valid channel set"],"tags":["notification","validation","mcp-tools"],"backgroundTag":null,"analyzedSha":"8ee26026ba6c11dec41a95fb3895a7162876caa1","analyzedAt":"2026-08-15T01:42:18.084Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}