{"record":{"id":"0e964de0fcd836db","repo":"ZhuLinsen/daily_stock_analysis","slug":"intelligence-source-name-already-exists-fields","errorCode":null,"errorMessage":"intelligence source name already exists: {fields['name']}","messagePattern":"intelligence source name already exists: (.+?)","errorType":"exception","errorClass":"IntelligenceServiceError","httpStatus":400,"severity":"error","filePath":"src/services/intelligence_service.py","lineNumber":153,"sourceCode":"    ):\n        self.repo = repository or IntelligenceRepository()\n        self.config = config or get_config()\n\n    @classmethod\n    def reset_auto_fetch_state(cls) -> None:\n        with cls._auto_fetch_condition:\n            cls._auto_fetch_in_progress = False\n            cls._auto_fetch_last_run_at = None\n            cls._auto_fetch_last_result = None\n            cls._auto_fetch_condition.notify_all()\n\n    def create_source(self, payload: Dict[str, Any]) -> Dict[str, Any]:\n        fields = self._normalize_source_fields(payload)\n        self._validate_url(fields[\"url\"])\n        try:\n            return self._source_to_dict(self.repo.create_source(fields))\n        except IntegrityError as exc:\n            raise IntelligenceServiceError(f\"intelligence source name already exists: {fields['name']}\") from exc\n\n    def list_sources(self, **filters: Any) -> Dict[str, Any]:\n        rows, total = self.repo.list_sources(**filters)\n        return {\n            \"items\": [self._source_to_dict(row) for row in rows],\n            \"total\": total,\n            \"page\": max(1, int(filters.get(\"page\") or 1)),\n            \"page_size\": max(1, min(int(filters.get(\"page_size\") or 50), 100)),\n        }\n\n    def list_source_templates(self, **filters: Any) -> Dict[str, Any]:\n        market = str(filters.get(\"market\") or \"\").strip().lower()\n        source_type = str(filters.get(\"source_type\") or \"\").strip().lower()\n        templates = []\n        for template in self._builtin_source_templates():\n            if market and template[\"market\"] != market:\n                continue\n            if source_type and template[\"source_type\"] != source_type:","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/services/intelligence_service.py#L135-L171","documentation":"IntelligenceService.create_source maps a DB IntegrityError (unique constraint on source name) into an IntelligenceServiceError. _normalize_source_fields strips and truncates the name to 100 chars before insert, so the collision is on the normalized name.","triggerScenarios":"POSTing a source whose name (after strip) equals an existing row's name; concurrent double-submit of the same create form; create_default_sources run after sources were already created.","commonSituations":"User double-clicks 'Create'; template-based creation colliding with previously created defaults; whitespace-only differences mistaken for unique names.","solutions":["List existing sources first (list_sources) and reuse or pick a distinct name","Make the create UI idempotent: disable submit while in flight and surface the duplicate error as a form-field message","On collision, switch to update_source with the existing id instead"],"exampleFix":"# before\nsvc.create_source({'name': '财联社', 'url': '...'})  # duplicate -> error\n# after\nexisting = next((s for s in svc.list_sources()['items'] if s['name']=='财联社'), None)\nif existing:\n    svc.update_source(existing['id'], {'url': '...'})\nelse:\n    svc.create_source({'name': '财联社', 'url': '...'})","handlingStrategy":"try-catch","validationCode":"existing = {s['name'] for s in svc.list_sources(page_size=100)['items']}\nif payload['name'].strip() in existing:\n    raise UserError('同名数据源已存在，请换一个名称')","typeGuard":null,"tryCatchPattern":"try:\n    svc.create_source(payload)\nexcept IntelligenceServiceError as e:\n    if 'already exists' in str(e):\n        show_field_error('name', '该名称已被占用')\n    else:\n        raise","preventionTips":["Disable the submit button while the request is in flight (prevents double-click duplicates)","Check name uniqueness against a fresh list_sources before create","Treat 'already exists' as a form validation error, not a 500"],"tags":["database","duplicate","intelligence","integrity-error"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}