{"record":{"id":"b7fa2ec3f38e4405","repo":"BerriAI/litellm","slug":"batch-upload-file-handle-must-be-seekable-so-it-ca","errorCode":null,"errorMessage":"Batch upload file handle must be seekable so it can be re-read for the GCS object name and the upload body.","messagePattern":"Batch upload file handle must be seekable so it can be re-read for the GCS object name and the upload body\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/vertex_ai/files/transformation.py","lineNumber":604,"sourceCode":"        with open(str(content), \"rb\") as handle:\n            yield from _iter_stripped_lines(handle)\n        return\n\n    if hasattr(content, \"read\"):\n        # The handle is read twice per upload (first-row probe for the GCS\n        # object name, then the body stream), so it must rewind to 0. A\n        # non-seekable handle would silently resume mid-stream and drop the\n        # already-consumed first row, so reject it loudly instead.\n        seek: Final = getattr(content, \"seek\", None)\n        if seek is None:\n            raise ValueError(\n                \"Batch upload file handle must be seekable; got a non-seekable \"\n                \"stream. Pass bytes, a path, or a seekable handle.\"\n            )\n        try:\n            seek(0)\n        except (OSError, ValueError) as e:\n            raise ValueError(\n                \"Batch upload file handle must be seekable so it can be re-read \"\n                \"for the GCS object name and the upload body.\"\n            ) from e\n        yield from _iter_stripped_lines(content)\n        return\n\n    raise ValueError(\"Unsupported file content type\")\n\n\ndef _iter_openai_jsonl_entries(\n    openai_file_content: FileTypes,\n) -> Iterator[dict[str, Any]]:\n    for line in _iter_openai_jsonl_lines(openai_file_content):\n        yield json.loads(line)\n\n\ndef _parse_vertex_batch_output_row(line: str) -> _VertexBatchRow:\n    row: Final[_VertexBatchRow] = json.loads(line)","sourceCodeStart":586,"sourceCodeEnd":622,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/vertex_ai/files/transformation.py#L586-L622","documentation":"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.","triggerScenarios":"Triggered when the batch upload file handle cannot be re-read for the GCS object name and upload body.","commonSituations":"See trigger scenarios.","solutions":["Provide a seekable file handle so it can be re-read for upload.","Read the content into bytes first if the stream is non-seekable."],"exampleFix":"data = stream.read(); file=io.BytesIO(data)","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}