{"record":{"id":"efe1a22b652b9584","repo":"ZhuLinsen/daily_stock_analysis","slug":"unsupported-source-type-source-type","errorCode":null,"errorMessage":"unsupported source_type: {source_type}","messagePattern":"unsupported source_type: (.+?)","errorType":"validation","errorClass":"IntelligenceServiceError","httpStatus":400,"severity":"error","filePath":"src/services/intelligence_service.py","lineNumber":374,"sourceCode":"                cls._auto_fetch_in_progress = False\n                cls._auto_fetch_condition.notify_all()\n        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:","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/services/intelligence_service.py#L356-L392","documentation":"Validation in _normalize_source_fields: source_type (default 'rss', lowercased) is not in _ALLOWED_SOURCE_TYPES = {'rss','atom','newsnow'}. Anything else is rejected before persistence.","triggerScenarios":"POSTing source_type like 'html', 'json', 'rss2', 'web', or 'RSS ' with stray chars that mangle after lower/strip (plain 'RSS' passes since it's lowercased).","commonSituations":"Assuming arbitrary feed types are supported; version drift after allowed set changed; frontend enum out of sync with backend.","solutions":["Use one of: rss, atom, newsnow (case-insensitive)","Fetch the allowed types from API docs/schema or list_source_templates examples before building the payload","For plain web-page sources, there is currently no supported type — use an RSS/atom feed URL instead"],"exampleFix":"# before\nsvc.create_source({'name':'x','url':'https://.../feed','source_type':'html'})\n# after\nsvc.create_source({'name':'x','url':'https://.../feed.xml','source_type':'rss'})","handlingStrategy":"type-guard","validationCode":"ALLOWED = {'rss', 'atom', 'newsnow'}\nsource_type = str(payload.get('source_type') or 'rss').strip().lower()\nif source_type not in ALLOWED:\n    raise UserError(f'source_type 仅支持 {sorted(ALLOWED)}')","typeGuard":"def is_valid_source_type(v) -> bool:\n    return str(v or 'rss').strip().lower() in {'rss', 'atom', 'newsnow'}","tryCatchPattern":"try:\n    svc.create_source(payload)\nexcept IntelligenceServiceError as e:\n    if 'unsupported source_type' in str(e):\n        payload['source_type'] = 'rss'\n        svc.create_source(payload)\n    else:\n        raise","preventionTips":["Build the type dropdown from the documented set {rss, atom, newsnow}","Lowercase user input client-side to match backend normalization","Keep client enums in sync with the API schema on upgrades"],"tags":["validation","intelligence","enum"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}