{"record":{"id":"a8a9c33bb8720665","repo":"ZhuLinsen/daily_stock_analysis","slug":"source-url-is-required","errorCode":null,"errorMessage":"source url is required","messagePattern":"source url is required","errorType":"validation","errorClass":"IntelligenceServiceError","httpStatus":400,"severity":"error","filePath":"src/services/intelligence_service.py","lineNumber":372,"sourceCode":"                cls._auto_fetch_last_run_at = datetime.now()\n                cls._auto_fetch_last_result = dict(result)\n                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        }","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/services/intelligence_service.py#L354-L390","documentation":"Validation in _normalize_source_fields: the url field, after str()/strip(), is empty. Note the check is only for non-emptiness here — the separate _validate_url call in create_source handles well-formedness.","triggerScenarios":"POSTing a source with url omitted, empty, or whitespace-only; template override setting url='' or None being stripped to empty.","commonSituations":"Form missing the URL field; API payload typo like 'urls' instead of 'url'; template default url empty.","solutions":["Provide a non-empty URL string (e.g. the RSS/atom feed endpoint)","Check the payload key is exactly 'url'","Client-side: mark URL required in the create-source form"],"exampleFix":"# before\nsvc.create_source({'name': 'news', 'url': ''})  # -> error\n# after\nsvc.create_source({'name': 'news', 'url': 'https://example.com/feed.xml'})","handlingStrategy":"validation","validationCode":"url = str(payload.get('url') or '').strip()\nif not url:\n    raise UserError('URL 不能为空')","typeGuard":"def has_source_url(payload: dict) -> bool:\n    return bool(str(payload.get('url') or '').strip())","tryCatchPattern":"try:\n    svc.create_source(payload)\nexcept IntelligenceServiceError as e:\n    if 'url is required' in str(e):\n        focus_field('url')\n    else:\n        raise","preventionTips":["Mark url required in the form; double-check the key is exactly 'url'","Validate non-empty before well-formedness — they are separate checks in the service"],"tags":["validation","intelligence","required-field"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}