{"record":{"id":"b98a90d40b19a147","repo":"ZhuLinsen/daily_stock_analysis","slug":"unsupported-scope-type-scope-type","errorCode":null,"errorMessage":"unsupported scope_type: {scope_type}","messagePattern":"unsupported scope_type: (.+?)","errorType":"validation","errorClass":"IntelligenceServiceError","httpStatus":400,"severity":"error","filePath":"src/services/intelligence_service.py","lineNumber":376,"sourceCode":"        return result\n\n    def _normalize_source_fields(self, payload: Dict[str, Any]) -> Dict[str, Any]:\n        name = str(payload.get(\"name\") or \"\").strip()\n        url = str(payload.get(\"url\") or \"\").strip()\n        source_type = str(payload.get(\"source_type\") or \"rss\").strip().lower()\n        scope_type = str(payload.get(\"scope_type\") or \"market\").strip().lower()\n        scope_value = str(payload.get(\"scope_value\") or \"\").strip() or None\n        market = str(payload.get(\"market\") or \"cn\").strip().lower()\n        enabled = bool(payload.get(\"enabled\", True))\n        description = str(payload.get(\"description\") or \"\").strip() or None\n        if not name:\n            raise IntelligenceServiceError(\"source name is required\")\n        if not url:\n            raise IntelligenceServiceError(\"source url is required\")\n        if source_type not in _ALLOWED_SOURCE_TYPES:\n            raise IntelligenceServiceError(f\"unsupported source_type: {source_type}\")\n        if scope_type not in _ALLOWED_SCOPE_TYPES:\n            raise IntelligenceServiceError(f\"unsupported scope_type: {scope_type}\")\n        if scope_type in {\"symbol\", \"sector\"} and not scope_value:\n            raise IntelligenceServiceError(f\"scope_value is required when scope_type={scope_type}\")\n        if market not in _ALLOWED_MARKETS:\n            raise IntelligenceServiceError(f\"unsupported market: {market}\")\n        return {\n            \"name\": name[:100],\n            \"source_type\": source_type,\n            \"url\": url,\n            \"enabled\": enabled,\n            \"scope_type\": scope_type,\n            \"scope_value\": scope_value[:64] if scope_value else None,\n            \"market\": market,\n            \"description\": description,\n        }\n\n    def _validate_url(self, raw_url: str, *, allow_no_url: bool = False) -> None:\n        if allow_no_url and raw_url.startswith(\"no-url:intel:\"):\n            return","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/services/intelligence_service.py#L358-L394","documentation":"Validation in _normalize_source_fields: scope_type (default 'market', lowercased) is not in _ALLOWED_SCOPE_TYPES = {'symbol','market','sector'}. The scope controls how fetched intelligence items are attached (whole market, one ticker, or a sector).","triggerScenarios":"POSTing scope_type like 'global', 'watchlist', 'industry', or 'Market ' with stray characters.","commonSituations":"Frontend dropdown built with extra options; consumer assuming a 'global' scope exists (the market value 'global' is a different field — market); typos/case handled by lower() but whitespace-only variants fail.","solutions":["Use one of: market, symbol, sector (case-insensitive)","Remember scope_value is required when scope_type is symbol or sector — supply it in the same request","Align client-side enums with the backend allowed set"],"exampleFix":"# before\nsvc.create_source({'name':'x','url':'...','scope_type':'global'})\n# after\nsvc.create_source({'name':'x','url':'...','scope_type':'market','market':'global'})","handlingStrategy":"type-guard","validationCode":"ALLOWED = {'symbol', 'market', 'sector'}\nscope_type = str(payload.get('scope_type') or 'market').strip().lower()\nif scope_type not in ALLOWED:\n    raise UserError(f'scope_type 仅支持 {sorted(ALLOWED)}')\nif scope_type in ('symbol', 'sector') and not (payload.get('scope_value') or '').strip():\n    raise UserError(f'scope_value 必填 when scope_type={scope_type}')","typeGuard":"def is_valid_scope_payload(p: dict) -> bool:\n    st = str(p.get('scope_type') or 'market').strip().lower()\n    if st not in {'symbol', 'market', 'sector'}:\n        return False\n    return st == 'market' or bool(str(p.get('scope_value') or '').strip())","tryCatchPattern":"try:\n    svc.create_source(payload)\nexcept IntelligenceServiceError as e:\n    if 'unsupported scope_type' in str(e):\n        payload['scope_type'] = 'market'\n        payload.pop('scope_value', None)\n        svc.create_source(payload)\n    else:\n        raise","preventionTips":["Use only market/symbol/sector; 'global' belongs to the market field, not scope_type","Supply scope_value whenever scope_type is symbol or sector","Derive scope options from the same constants the backend validates against"],"tags":["validation","intelligence","enum"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}