BerriAI/litellm · error · ValueError
Chunk is not a string: {chunk}
Error message
Chunk is not a string: {chunk} What it means
OCIGenericStreamingChunkHandler.chunk_creator validates each SSE event yielded by the stream wrapper; it raises ValueError when a chunk is not a Python str. The handler only accepts raw 'data:'-prefixed SSE lines, so any other object type means the upstream contract (the _iter_sse_events/_aiter_sse_events pipeline) was violated or the wrapper was fed manually with bytes/dicts.
Source
Thrown at litellm/llms/oci/chat/transformation.py:748
custom_llm_provider=custom_llm_provider,
stream_options=stream_options,
make_call=make_call,
_response_headers=_response_headers,
)
# Tracks whether any prior Cohere chunk in this stream has emitted
# tool calls. The Cohere handler uses this to decide whether the
# terminal consolidation chunk's tool calls are duplicates (suppress)
# or the only copy of the tool calls (pass through).
self._cohere_tool_calls_emitted = False
# Analogous flag for text content. Lets the Cohere handler distinguish
# the common case (prior deltas already streamed the text, so the
# terminal chunk's text is a duplicate to suppress) from the degenerate
# single-event case (terminal chunk carries the only copy of the text).
self._cohere_text_emitted = False
def chunk_creator(self, chunk: Any) -> ModelResponseStream:
if not isinstance(chunk, str):
raise ValueError(f"Chunk is not a string: {chunk}")
if not chunk.startswith("data:"):
raise ValueError(f"Chunk does not start with 'data:': {chunk}")
try:
dict_chunk: Final = json.loads(chunk[5:])
except json.JSONDecodeError as e:
raise OCIError(
status_code=500,
message=f"Chunk cannot be parsed as JSON: {e}",
)
if dict_chunk.get("apiFormat") == "COHERE":
result: Final = handle_cohere_stream_chunk(
dict_chunk,
prior_tool_calls_emitted=self._cohere_tool_calls_emitted,
prior_text_emitted=self._cohere_text_emitted,
)
if not self._cohere_tool_calls_emitted:
for choice in result.choices:View on GitHub (pinned to 6c2dcb801b)
Solutions
- If you consume OCIStreamWrapper directly, iterate it rather than calling chunk_creator yourself with parsed objects.
- In tests, feed 'data:{...}' string lines, not dicts (use the model's transform_response instead for parsed chunks).
- If a proxy sits between you and OCI, bypass it to confirm the SSE framing is intact.
- Upgrade litellm — changes to the SSE iteration contract are fixed in newer patches.
Example fix
# before (test feeding dicts)
handler.chunk_creator({"apiFormat": "COHERE", ...}) # ValueError
# after (feed raw SSE strings)
handler.chunk_creator('data:{"apiFormat": "COHERE", ...}') Defensive patterns
Strategy: type-guard
Validate before calling
def is_sse_data_line(chunk) -> bool:
return isinstance(chunk, str) and chunk.startswith("data:") Type guard
from typing import Any
def is_sse_chunk(chunk: Any) -> bool: # type guard for manual iteration
return isinstance(chunk, str) Try / catch
try:
parsed = handler.chunk_creator(chunk)
except ValueError:
logger.error("unexpected stream chunk %r", chunk)
raise Prevention
- Never call chunk_creator directly; consume the litellm stream iterator.
- In tests, always feed 'data:'-prefixed string lines.
- Keep intermediaries from re-chunking the SSE body.
When it happens
Trigger: OCIStreamWrapper is iterated manually (custom embedding of the handler), or an API/proxy in front of OCI re-chunks the SSE body so the text iterator yields non-string objects; also triggered by passing a mock/fake stream of dicts in tests instead of 'data:{json}' strings.
Common situations: Almost always a programming error on the caller's side: unit tests stubbing the stream with parsed dict chunks, wrapping the OCIStreamWrapper in another generator that yields JSON objects, or a transport-layer change (httpx version behavior with iter_text) producing bytes. Rare in normal litellm.completion usage because the pipeline is internal.
Related errors
- Chunk cannot be parsed as CohereStreamChunk: {e}
- Chunk does not start with 'data:': {chunk}
- Chunk cannot be parsed as JSON: {e}
- Failed to decode JSON from chunk: {chunk}
- Error parsing chunk: {e}, Received chunk: {chunk}
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/574869ff91ec8e6a.
Report an issue: GitHub.