{"record":{"id":"65169e04a4f3f21c","repo":"BerriAI/litellm","slug":"self-custom-llm-provider-raised-a-streaming-erro","errorCode":null,"errorMessage":"{self.custom_llm_provider} raised a streaming error - finish_reason: error, no content string given. Received Chunk={response_obj}","messagePattern":"(.+?) raised a streaming error - finish_reason: error, no content string given\\. Received Chunk=(.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/streaming_handler.py","lineNumber":1436,"sourceCode":"                self.system_fingerprint = chunk.system_fingerprint\n            if response_obj[\"is_finished\"]:\n                self.received_finish_reason = response_obj[\"finish_reason\"]\n        else:  # openai / azure chat model\n            if self.custom_llm_provider in [\n                LlmProviders.AZURE.value,\n                LlmProviders.AZURE_AI.value,\n            ]:\n                if isinstance(chunk, BaseModel) and hasattr(chunk, \"model\"):\n                    # for azure, we need to pass the model from the original chunk\n                    self.model = getattr(chunk, \"model\", self.model)\n            response_obj = self.handle_openai_chat_completion_chunk(chunk)\n            if response_obj is None:\n                return _ProviderChunkEarlyReturn(None)\n            completion_obj[\"content\"] = response_obj[\"text\"]\n            self.intermittent_finish_reason = response_obj.get(\"finish_reason\", None)\n            if response_obj[\"is_finished\"]:\n                if response_obj[\"finish_reason\"] == \"error\":\n                    raise Exception(\n                        f\"{self.custom_llm_provider} raised a streaming error - finish_reason: error, no content string given. Received Chunk={response_obj}\"\n                    )\n                self.received_finish_reason = response_obj[\"finish_reason\"]\n            if response_obj.get(\"original_chunk\", None) is not None:\n                if hasattr(response_obj[\"original_chunk\"], \"id\"):\n                    model_response = self.set_model_id(response_obj[\"original_chunk\"].id, model_response)\n                if hasattr(response_obj[\"original_chunk\"], \"system_fingerprint\"):\n                    model_response.system_fingerprint = response_obj[\"original_chunk\"].system_fingerprint\n                    self.system_fingerprint = response_obj[\"original_chunk\"].system_fingerprint\n            if response_obj[\"logprobs\"] is not None:\n                model_response.choices[0].logprobs = response_obj[\"logprobs\"]\n\n            if response_obj[\"usage\"] is not None:\n                if isinstance(response_obj[\"usage\"], dict):\n                    setattr(\n                        model_response,\n                        \"usage\",\n                        litellm.Usage(","sourceCodeStart":1418,"sourceCodeEnd":1454,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/streaming_handler.py#L1418-L1454","documentation":"Raised while processing a streaming response: the provider sent a chunk with finish_reason == 'error' and no content string. LiteLLM's streaming handler treats an error finish reason as a hard failure because it cannot distinguish a provider-side abort from a normal completion, and it embeds the raw Chunk in the message for diagnosis.","triggerScenarios":"A streaming completion() call (stream=True) where the upstream LLM provider terminates the stream with finish_reason 'error' - e.g. Azure/OpenAI-compatible gateways, Vertex, or Bedrock emitting an error termination frame mid-stream, or content-filter terminations.","commonSituations":"Long streaming generations cut off server-side; Azure OpenAI content-moderation kills; unstable OpenAI-compatible proxies (vLLM, self-hosted gateways) that map internal errors to finish_reason='error'; transient provider incidents under load.","solutions":["Retry the request (with or without stream=True) - most occurrences are transient provider-side aborts; check the provider status page.","Inspect the full Received Chunk= payload in the exception for a provider error code (e.g. content_filter) and fix the prompt/model config accordingly.","If behind an OpenAI-compatible proxy, check or upgrade it - some gateways emit finish_reason='error' on timeout; raise their timeout.","If it recurs on one deployment, route around it with litellm.Router fallback deployments and num_retries>=1."],"exampleFix":"# before\nresp = await litellm.acompletion(model=\"azure/gpt-4o\", messages=msgs, stream=True)\nasync for e in resp: process(e)  # raises mid-iteration\n\n# after\nfrom litellm import Router\nrouter = Router(model_list=[\n  {\"model_name\": \"gpt-4o\", \"litellm_params\": {\"model\": \"azure/gpt-4o-primary\"}},\n  {\"model_name\": \"gpt-4o\", \"litellm_params\": {\"model\": \"azure/gpt-4o-backup\"}},\n], num_retries=2, timeout=120)\nresp = await router.acompletion(model=\"gpt-4o\", messages=msgs, stream=True)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    async for event in stream: process(event)\nexcept Exception as e:  # handler raises a plain Exception\n    if \"raised a streaming error\" in str(e):\n        resp = await router.acompletion(...)  # retry once, non-stream or fallback model\n    else:\n        raise","preventionTips":["Use litellm.Router with num_retries>=1 and fallback deployments for streaming calls.","Set stream_timeout generously for long generations.","Log the full Received Chunk payload when it fires - the provider error code determines the real fix."],"tags":["streaming","provider-error","retry","transient"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}