{"record":{"id":"c81cf2d66fa4b3cd","repo":"NanmiCoder/MediaCrawler","slug":"bilistorefactory-create-store-invalid-save-optio","errorCode":null,"errorMessage":"[BiliStoreFactory.create_store] Invalid save option only supported csv or db or json or sqlite or mongodb or excel ...","messagePattern":"\\[BiliStoreFactory\\.create_store\\] Invalid save option only supported csv or db or json or sqlite or mongodb or excel \\.\\.\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"store/bilibili/__init__.py","lineNumber":51,"sourceCode":"\n\nclass BiliStoreFactory:\n    STORES = {\n        \"csv\": BiliCsvStoreImplement,\n        \"db\": BiliDbStoreImplement,\n        \"postgres\": BiliDbStoreImplement,\n        \"json\": BiliJsonStoreImplement,\n        \"jsonl\": BiliJsonlStoreImplement,\n        \"sqlite\": BiliSqliteStoreImplement,\n        \"mongodb\": BiliMongoStoreImplement,\n        \"excel\": BiliExcelStoreImplement,\n    }\n\n    @staticmethod\n    def create_store() -> AbstractStore:\n        store_class = BiliStoreFactory.STORES.get(config.SAVE_DATA_OPTION)\n        if not store_class:\n            raise ValueError(\"[BiliStoreFactory.create_store] Invalid save option only supported csv or db or json or sqlite or mongodb or excel ...\")\n        return store_class()\n\n\nasync def update_bilibili_video(video_item: Dict):\n    video_item_view: Dict = video_item.get(\"View\")\n    video_user_info: Dict = video_item_view.get(\"owner\")\n    video_item_stat: Dict = video_item_view.get(\"stat\")\n    video_id = str(video_item_view.get(\"aid\"))\n    save_content_item = {\n        \"video_id\": video_id,\n        \"video_type\": \"video\",\n        \"title\": video_item_view.get(\"title\", \"\")[:500],\n        \"desc\": video_item_view.get(\"desc\", \"\")[:500],\n        \"create_time\": video_item_view.get(\"pubdate\"),\n        \"creator_hash\": anonymize_user_id(video_user_info.get(\"mid\")),  # 创作者匿名哈希(不存原始 mid)\n        \"nickname\": mask_nickname(video_user_info.get(\"name\")),  # 用户昵称(已脱敏)\n        \"liked_count\": str(video_item_stat.get(\"like\", \"\")),\n        \"disliked_count\": str(video_item_stat.get(\"dislike\", \"\")),","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/NanmiCoder/MediaCrawler/blob/d6f7c5bb906b6dac40ddf343ef9e26438a3de092/store/bilibili/__init__.py#L33-L69","documentation":"Raised by BiliStoreFactory.create_store() when config.SAVE_DATA_OPTION does not match any key in the platform's STORES registry (csv, db, postgres, json, jsonl, sqlite, mongodb, excel). It is a fail-fast startup check so an unknown storage backend is caught before any crawl data is written.","triggerScenarios":"Setting SAVE_DATA_OPTION to an unsupported value ('mysql', 'tsv', 'redis'), a case mismatch ('CSV'), or a value valid in another fork but not registered here. Raised the first time a bilibili store is created during a crawl.","commonSituations":"Editing config/base_config.py SAVE_DATA_OPTION to a DB name that is not implemented; trailing whitespace in the config string; copying a config from documentation for a different version.","solutions":["Set SAVE_DATA_OPTION to one of the exact registry keys: csv, db, postgres, json, jsonl, sqlite, mongodb, excel","Check for typos, case errors, and stray whitespace in config/base_config.py or the overriding env var","For MySQL specifically: 'db' is the aiomysql-backed implementation — use that key, not 'mysql'","If you truly need a new backend, register it in BiliStoreFactory.STORES before selecting it"],"exampleFix":"// before\nSAVE_DATA_OPTION = \"mysql\"\n\n// after\nSAVE_DATA_OPTION = \"db\"  # aiomysql implementation; or \"sqlite\"/\"postgres\"","handlingStrategy":"validation","validationCode":"from store.bilibili import BiliStoreFactory\n\nif config.SAVE_DATA_OPTION not in BiliStoreFactory.STORES:\n    raise SystemExit(\n        f\"SAVE_DATA_OPTION={config.SAVE_DATA_OPTION!r} invalid; \"\n        f\"choose from {sorted(BiliStoreFactory.STORES)}\"\n    )","typeGuard":"def is_valid_save_option(opt: str) -> bool:\n    return isinstance(opt, str) and opt in BiliStoreFactory.STORES","tryCatchPattern":"try:\n    store = BiliStoreFactory.create_store()\nexcept ValueError as e:\n    raise SystemExit(f\"fix config before crawling: {e}\") from e","preventionTips":["Validate SAVE_DATA_OPTION once at startup against the platform registry","Keep the value lowercase and exactly match a registry key","Use 'sqlite'/'json' for dependency-free first runs"],"tags":["configuration","storage","bilibili","startup"],"backgroundTag":null,"analyzedSha":"d6f7c5bb906b6dac40ddf343ef9e26438a3de092","analyzedAt":"2026-08-15T01:39:07.505Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}