{"record":{"id":"c92fb586a40689b7","repo":"headroomlabs-ai/headroom","slug":"unknown-provider-provider","errorCode":null,"errorMessage":"Unknown provider: {provider}","messagePattern":"Unknown provider: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"headroom/ccr/batch_processor.py","lineNumber":321,"sourceCode":"            messages: The messages including tool results.\n            tools: The tools list.\n            request_context: The request context.\n            batch_context: The batch context.\n            provider: The provider type.\n\n        Returns:\n            The API response.\n        \"\"\"\n        if provider == \"anthropic\":\n            return await self._anthropic_continuation(\n                messages, tools, request_context, batch_context\n            )\n        elif provider == \"openai\":\n            return await self._openai_continuation(messages, tools, request_context, batch_context)\n        elif provider == \"google\":\n            return await self._google_continuation(messages, tools, request_context, batch_context)\n        else:\n            raise ValueError(f\"Unknown provider: {provider}\")\n\n    async def _anthropic_continuation(\n        self,\n        messages: list[dict[str, Any]],\n        tools: list[dict[str, Any]] | None,\n        request_context: BatchRequestContext,\n        batch_context: BatchContext,\n    ) -> dict[str, Any]:\n        \"\"\"Make Anthropic continuation call.\"\"\"\n        url = f\"{self.api_urls['anthropic']}/v1/messages\"\n\n        headers = {\n            \"Content-Type\": \"application/json\",\n            \"anthropic-version\": \"2023-06-01\",\n        }\n        if batch_context.api_key:\n            headers[\"x-api-key\"] = batch_context.api_key\n","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/ccr/batch_processor.py#L303-L339","documentation":"In the CCR batch processor, continuation calls are dispatched per provider: 'anthropic', 'openai', or 'google'. Any other provider string reaching _continue_for (batch_processor.py:321) hits the else branch and raises ValueError. The value flows in from the provider field of a batch request/context, so the error indicates a batch entry carrying a provider the dispatcher does not know.","triggerScenarios":"Submitting a batch request whose provider field is not exactly one of the three supported lowercase strings — e.g. 'azure', 'bedrock', 'mistral', 'ANTHROPIC' (wrong case), or 'openai-compatible'.","commonSituations":"Adding a new provider to a config but not to the dispatcher; case or whitespace mismatches from user-edited batch JSON; forwarding a vendor-alias provider name from an upstream gateway.","solutions":["Set the request's provider to one of 'anthropic', 'openai', 'google' (exact lowercase)","Normalize/strip provider strings at ingestion: provider.strip().lower() before dispatch","If you need a new provider, implement a _<provider>_continuation method and add an elif branch in the dispatcher","Check the batch file/context for typos in the provider field"],"exampleFix":"# before\nresp = await bp._continue_for(provider=\"Azure\", ...)  # ValueError: Unknown provider: Azure\n\n# after\nresp = await bp._continue_for(provider=\"openai\", ...)","handlingStrategy":"type-guard","validationCode":"SUPPORTED_PROVIDERS = {\"anthropic\", \"openai\", \"google\"}\nprovider = provider.strip().lower() if provider else \"\"\nif provider not in SUPPORTED_PROVIDERS:\n    raise ValueError(f\"unsupported provider {provider!r}; expected one of {sorted(SUPPORTED_PROVIDERS)}\")","typeGuard":"from typing import Literal\nProvider = Literal[\"anthropic\", \"openai\", \"google\"]\n\ndef is_supported_provider(p: str) -> TypeGuard[Provider]:\n    return p in {\"anthropic\", \"openai\", \"google\"}","tryCatchPattern":"try:\n    resp = await processor._continue_for(provider=provider, ...)\nexcept ValueError as e:\n    if \"Unknown provider\" in str(e):\n        reject_batch_entry(entry, reason=str(e))\n    else:\n        raise","preventionTips":["Validate provider at batch-file ingestion, not at continuation time","Keep a single PROVIDER literal union as the source of truth shared with the dispatcher","Reject unknown providers early with a clear per-entry error so one bad row cannot kill the batch"],"tags":["ccr","batch","provider","dispatch","valueerror"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}