Skip to content

Commit 3e92666

Browse files
chengzeyiclaude
andcommitted
Raise a clear error when a non-seekable upload stream exceeds 200 MB
The stream was read up to the limit plus one byte and that truncated size was declared to the API, so an oversize stream failed with a raw HTTP 413 instead of a local error. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EEvHR83ShvnHGR8VgJcsWV
1 parent 3389f5b commit 3e92666

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

‎src/wavespeed/api/client.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,8 @@ def upload(self, file: str | BinaryIO, *, timeout: float | None = None) -> str:
587587
URL of the uploaded file.
588588
589589
Raises:
590-
ValueError: If API key is not configured.
590+
ValueError: If API key is not configured, or a non-seekable
591+
stream exceeds the 200 MB upload limit.
591592
FileNotFoundError: If file path does not exist.
592593
RuntimeError: If upload fails.
593594
@@ -627,7 +628,10 @@ def upload(self, file: str | BinaryIO, *, timeout: float | None = None) -> str:
627628
size = stream.tell() - start
628629
stream.seek(start)
629630
except (AttributeError, OSError, io.UnsupportedOperation):
630-
data = stream.read(200 * 1024 * 1024 + 1)
631+
max_size = 200 * 1024 * 1024
632+
data = stream.read(max_size + 1)
633+
if len(data) > max_size:
634+
raise ValueError("File size exceeds the 200 MB limit.")
631635
stream = io.BytesIO(data)
632636
size = len(data)
633637

‎tests/test_api.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,22 @@ def test_upload_file_not_found(self):
582582
with self.assertRaises(FileNotFoundError):
583583
client.upload("/nonexistent/path/to/file.png")
584584

585+
@patch("wavespeed.api.client.requests.post")
586+
def test_upload_oversize_stream_raises(self, mock_post):
587+
"""A non-seekable stream over the limit fails before any request."""
588+
589+
class Pipe:
590+
name = "clip.mp4"
591+
592+
def read(self, n):
593+
return bytes(n)
594+
595+
client = Client(api_key="test-key")
596+
with self.assertRaises(ValueError) as ctx:
597+
client.upload(Pipe())
598+
self.assertIn("200 MB", str(ctx.exception))
599+
mock_post.assert_not_called()
600+
585601
def test_upload_raises_without_api_key(self):
586602
"""Test that upload raises ValueError without API key."""
587603
client = Client()

0 commit comments

Comments
 (0)