BerriAI/litellm · error · ValueError

Batch upload file handle must be seekable so it can be re-re

Error message

Batch upload file handle must be seekable so it can be re-read for the GCS object name and the upload body.

What it means

Batch file iteration guard: the handle exposes seek() but calling seek(0) raised OSError/ValueError, so the stream cannot be rewound between the GCS object-name probe and the upload body read, and the input is rejected.

Source

Thrown at litellm/llms/vertex_ai/files/transformation.py:604

        with open(str(content), "rb") as handle:
            yield from _iter_stripped_lines(handle)
        return

    if hasattr(content, "read"):
        # The handle is read twice per upload (first-row probe for the GCS
        # object name, then the body stream), so it must rewind to 0. A
        # non-seekable handle would silently resume mid-stream and drop the
        # already-consumed first row, so reject it loudly instead.
        seek: Final = getattr(content, "seek", None)
        if seek is None:
            raise ValueError(
                "Batch upload file handle must be seekable; got a non-seekable "
                "stream. Pass bytes, a path, or a seekable handle."
            )
        try:
            seek(0)
        except (OSError, ValueError) as e:
            raise ValueError(
                "Batch upload file handle must be seekable so it can be re-read "
                "for the GCS object name and the upload body."
            ) from e
        yield from _iter_stripped_lines(content)
        return

    raise ValueError("Unsupported file content type")


def _iter_openai_jsonl_entries(
    openai_file_content: FileTypes,
) -> Iterator[dict[str, Any]]:
    for line in _iter_openai_jsonl_lines(openai_file_content):
        yield json.loads(line)


def _parse_vertex_batch_output_row(line: str) -> _VertexBatchRow:
    row: Final[_VertexBatchRow] = json.loads(line)

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Provide a seekable file handle so it can be re-read for upload.
  2. Read the content into bytes first if the stream is non-seekable.

Example fix

data = stream.read(); file=io.BytesIO(data)
Defensive patterns

Strategy: validation

When it happens

Trigger: Triggered when the batch upload file handle cannot be re-read for the GCS object name and upload body.

Common situations: See trigger scenarios.


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/b7fa2ec3f38e4405. Report an issue: GitHub.