{"record":{"id":"507121ab03149e51","repo":"zylon-ai/private-gpt","slug":"web-scraper-provider-name-is-not-registered-a","errorCode":null,"errorMessage":"Web scraper provider '{name}' is not registered. Available: {available}","messagePattern":"Web scraper provider '(.+?)' is not registered\\. Available: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/web/scraper/registry.py","lineNumber":30,"sourceCode":"    name: str, provider: WebScraperProviderFactory\n) -> None:\n    _PROVIDERS[name] = provider\n\n\nclass WebScraperProviderRegistry:\n    def __init__(self, settings: Settings) -> None:\n        self._settings = settings\n        self._providers: dict[str, WebScraperProvider] = {}\n\n    def get_provider(self, name: str) -> WebScraperProvider:\n        provider = self._providers.get(name)\n        if provider is not None:\n            return provider\n\n        provider_factory = _PROVIDERS.get(name)\n        if provider_factory is None:\n            available = \", \".join(sorted(_PROVIDERS)) or \"none\"\n            raise ValueError(\n                f\"Web scraper provider '{name}' is not registered. \"\n                f\"Available: {available}\"\n            )\n        provider = provider_factory(self._settings)\n        self._providers[name] = provider\n        return provider\n\n    async def close_all(self) -> None:\n        providers, self._providers = list(self._providers.values()), {}\n        for provider in providers:\n            await provider.close()\n","sourceCodeStart":12,"sourceCodeEnd":42,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/web/scraper/registry.py#L12-L42","documentation":"ValueError raised by the web scraper registry's get_provider when the requested provider name is neither cached in the instance map nor present in the module-level _PROVIDERS factory map. The message enumerates the registered provider names.","triggerScenarios":"Calling get_provider(name) with a misspelled or unregistered provider (e.g. 'trafilatura' vs 'trafilatura_scraper', or a plugin provider whose registration never ran); case-sensitive mismatch.","commonSituations":"Settings-driven scraper selection (web.scraper.provider) with a stale name after an upgrade; custom scrapers expected to auto-register but their module was never imported; copy-pasted provider names from other projects.","solutions":["Use one of the provider names listed in the error message (exact spelling/case)","For custom scrapers, ensure their module is imported and their factory is added to _PROVIDERS before get_provider is called","Log sorted(_PROVIDERS) at startup to keep an inventory of valid names"],"exampleFix":"# before\nprovider = registry.get_provider(\"BeautifulSoup\")\n# after\nprovider = registry.get_provider(\"beautifulsoup\")  # exact key from _PROVIDERS","handlingStrategy":"validation","validationCode":"from private_gpt.components.web.scraper.registry import _PROVIDERS\n\ndef provider_exists(name: str) -> bool:\n    return name in _PROVIDERS\n\nassert provider_exists(name), f\"unknown web scraper {name!r}; known: {sorted(_PROVIDERS)}\"","typeGuard":null,"tryCatchPattern":"try:\n    provider = registry.get_provider(name)\nexcept ValueError as e:\n    if \"is not registered\" in str(e):\n        # parse the Available list from the message, correct the name, retry once\n        raise","preventionTips":["Drive scraper selection from an enum/constant list, not free-form config strings","Import custom scraper modules at startup so their _PROVIDERS entries exist before use","Log sorted(_PROVIDERS) at boot to keep an accurate inventory"],"tags":["web-scraping","provider-registry","configuration"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}