NanmiCoder/MediaCrawler · error · ValueError

[BiliStoreFactory.create_store] Invalid save option only sup

Error message

[BiliStoreFactory.create_store] Invalid save option only supported csv or db or json or sqlite or mongodb or excel ...

What it means

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.

Source

Thrown at store/bilibili/__init__.py:51


class BiliStoreFactory:
    STORES = {
        "csv": BiliCsvStoreImplement,
        "db": BiliDbStoreImplement,
        "postgres": BiliDbStoreImplement,
        "json": BiliJsonStoreImplement,
        "jsonl": BiliJsonlStoreImplement,
        "sqlite": BiliSqliteStoreImplement,
        "mongodb": BiliMongoStoreImplement,
        "excel": BiliExcelStoreImplement,
    }

    @staticmethod
    def create_store() -> AbstractStore:
        store_class = BiliStoreFactory.STORES.get(config.SAVE_DATA_OPTION)
        if not store_class:
            raise ValueError("[BiliStoreFactory.create_store] Invalid save option only supported csv or db or json or sqlite or mongodb or excel ...")
        return store_class()


async def update_bilibili_video(video_item: Dict):
    video_item_view: Dict = video_item.get("View")
    video_user_info: Dict = video_item_view.get("owner")
    video_item_stat: Dict = video_item_view.get("stat")
    video_id = str(video_item_view.get("aid"))
    save_content_item = {
        "video_id": video_id,
        "video_type": "video",
        "title": video_item_view.get("title", "")[:500],
        "desc": video_item_view.get("desc", "")[:500],
        "create_time": video_item_view.get("pubdate"),
        "creator_hash": anonymize_user_id(video_user_info.get("mid")),  # 创作者匿名哈希(不存原始 mid)
        "nickname": mask_nickname(video_user_info.get("name")),  # 用户昵称(已脱敏)
        "liked_count": str(video_item_stat.get("like", "")),
        "disliked_count": str(video_item_stat.get("dislike", "")),

View on GitHub (pinned to d6f7c5bb90)

Solutions

  1. Set SAVE_DATA_OPTION to one of the exact registry keys: csv, db, postgres, json, jsonl, sqlite, mongodb, excel
  2. Check for typos, case errors, and stray whitespace in config/base_config.py or the overriding env var
  3. For MySQL specifically: 'db' is the aiomysql-backed implementation — use that key, not 'mysql'
  4. If you truly need a new backend, register it in BiliStoreFactory.STORES before selecting it

Example fix

// before
SAVE_DATA_OPTION = "mysql"

// after
SAVE_DATA_OPTION = "db"  # aiomysql implementation; or "sqlite"/"postgres"
Defensive patterns

Strategy: validation

Validate before calling

from store.bilibili import BiliStoreFactory

if config.SAVE_DATA_OPTION not in BiliStoreFactory.STORES:
    raise SystemExit(
        f"SAVE_DATA_OPTION={config.SAVE_DATA_OPTION!r} invalid; "
        f"choose from {sorted(BiliStoreFactory.STORES)}"
    )

Type guard

def is_valid_save_option(opt: str) -> bool:
    return isinstance(opt, str) and opt in BiliStoreFactory.STORES

Try / catch

try:
    store = BiliStoreFactory.create_store()
except ValueError as e:
    raise SystemExit(f"fix config before crawling: {e}") from e

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of NanmiCoder/MediaCrawler@d6f7c5bb90 (2026-08-15). Data as JSON: /api/errors/c81cf2d66fa4b3cd. Report an issue: GitHub.