{"record":{"id":"f685260a5cc47664","repo":"sansan0/TrendRadar","slug":"invalid-parameter","errorCode":"INVALID_PARAMETER","errorMessage":"无效的洞察类型: {insight_type}","messagePattern":"无效的洞察类型: (.+?)","errorType":"error_code","errorClass":"InvalidParameterError","httpStatus":null,"severity":"error","filePath":"mcp_server/tools/analytics.py","lineNumber":143,"sourceCode":"                - \"platform_activity\": 平台活跃度统计（统计各平台发布频率和活跃时间）\n                - \"keyword_cooccur\": 关键词共现分析（分析关键词同时出现的模式）\n            topic: 话题关键词（可选，platform_compare模式适用）\n            date_range: 日期范围，格式: {\"start\": \"YYYY-MM-DD\", \"end\": \"YYYY-MM-DD\"}\n            min_frequency: 最小共现频次（keyword_cooccur模式），默认3\n            top_n: 返回TOP N结果（keyword_cooccur模式），默认20\n\n        Returns:\n            数据洞察分析结果字典\n\n        Examples:\n            - analyze_data_insights_unified(insight_type=\"platform_compare\", topic=\"人工智能\")\n            - analyze_data_insights_unified(insight_type=\"platform_activity\", date_range={...})\n            - analyze_data_insights_unified(insight_type=\"keyword_cooccur\", min_frequency=5)\n        \"\"\"\n        try:\n            # 参数验证\n            if insight_type not in [\"platform_compare\", \"platform_activity\", \"keyword_cooccur\"]:\n                raise InvalidParameterError(\n                    f\"无效的洞察类型: {insight_type}\",\n                    suggestion=\"支持的类型: platform_compare, platform_activity, keyword_cooccur\"\n                )\n\n            # 根据洞察类型调用相应方法\n            if insight_type == \"platform_compare\":\n                return self.compare_platforms(\n                    topic=topic,\n                    date_range=date_range\n                )\n            elif insight_type == \"platform_activity\":\n                return self.get_platform_activity_stats(\n                    date_range=date_range\n                )\n            else:  # keyword_cooccur\n                return self.analyze_keyword_cooccurrence(\n                    min_frequency=min_frequency,\n                    top_n=top_n","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/sansan0/TrendRadar/blob/8ee26026ba6c11dec41a95fb3895a7162876caa1/mcp_server/tools/analytics.py#L125-L161","documentation":"The generic Webhook send function in senders.py requires a caller-supplied content-splitting function (split_content_func) because it must batch long messages to the webhook's size limit. It refuses to run with None, raising ValueError immediately, rather than silently sending a truncated or oversized payload. This is a programming/parameter error at the call site, not an environmental issue.","triggerScenarios":"Calling the send function without passing split_content_func (it has no default), passing split_content_func=None explicitly, or forwarding **kwargs from a dict that never set the key. Also happens when a new caller copies the signature but only fills webhook_url/content.","commonSituations":"Integrating a new notification channel and forgetting the splitter; refactoring that renames the kwarg (e.g. split_func vs split_content_func) so None arrives; building the kwargs dict dynamically and conditionally skipping the splitter; tests constructing minimal calls.","solutions":["Pass an existing splitter: reuse the module's split function used by other senders (e.g. split_content for wework) matching your webhook's byte limit.","If your content is always short, pass a trivial splitter: lambda text, size: [text] (respecting the batch_size contract).","Check the function signature/docstring (read with inspect.signature) to confirm the exact parameter name before wiring a custom caller.","Write a smoke test for the new channel that actually sends to a mock webhook so missing-argument bugs surface in CI."],"exampleFix":"# before\nsend_generic_webhook(\n    webhook_url=url,\n    content=report_text,\n    split_content_func=None,  # ValueError\n)\n\n# after\nfrom trendradar.notification.senders import split_content\n\nsend_generic_webhook(\n    webhook_url=url,\n    content=report_text,\n    split_content_func=split_content,  # batches text to size limit\n    batch_size=4096,\n)","handlingStrategy":"type-guard","validationCode":"import inspect\n\ndef splitter_ok(func) -> bool:\n    \"\"\"Splitter must be callable and accept (content, batch_size).\"\"\"\n    if not callable(func):\n        return False\n    try:\n        sig = inspect.signature(func)\n        sig.bind(\"text\", 4096)\n        return True\n    except TypeError:\n        return False\n\nassert splitter_ok(split_content_func), \"pass a real split function\"","typeGuard":"from typing import Callable, List, Optional\n\ndef is_split_content_func(func) -> bool:\n    \"\"\"True when func is a callable taking (text, size) — guards the required param.\"\"\"\n    if not callable(func):\n        return False\n    try:\n        inspect.signature(func).bind(\"text\", 4096)\n        return True\n    except TypeError:\n        return False","tryCatchPattern":null,"preventionTips":["Read the signature with inspect.signature before wiring new senders; required callables with no default are contract points.","Reuse the module's existing splitter instead of writing your own; only substitute one that honors the same batch semantics.","Add a CI smoke test per notification channel against a mock webhook so missing-parameter bugs fail in tests, not production."],"tags":["notification","webhook","api-misuse","parameter"],"backgroundTag":null,"analyzedSha":"8ee26026ba6c11dec41a95fb3895a7162876caa1","analyzedAt":"2026-08-15T01:42:18.084Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}