reflex-dev/reflex · error · RuntimeError
Upload handler returned before consuming all upload chunks.
Error message
Upload handler returned before consuming all upload chunks.
What it means
The streaming upload iterator verifies the background consumer task is still alive before enqueueing chunks. When the handler task has finished (returned, errored, or was cancelled) while chunks remain, _raise_if_consumer_finished raises RuntimeError, chained from the task's exception if any.
Source
Thrown at packages/reflex-components-core/src/reflex_components_core/core/_upload.py:250
self._condition.notify_all()
def _raise_if_consumer_finished(self) -> None:
"""Raise if the consumer task exited before draining the iterator.
Raises:
RuntimeError: If the consumer task completed before draining the iterator.
"""
if self._consumer_task is None or not self._consumer_task.done():
return
try:
task_exc = self._consumer_task.exception()
except asyncio.CancelledError as err:
task_exc = err
msg = "Upload handler returned before consuming all upload chunks."
if task_exc is not None:
raise RuntimeError(msg) from task_exc
raise RuntimeError(msg)
def _wake_waiters(self, task: asyncio.Future[Any]) -> None:
"""Wake any producers or consumers blocked on the iterator condition.
Args:
task: The completed consumer task.
"""
task.get_loop().create_task(self._notify_waiters())
async def _notify_waiters(self) -> None:
"""Notify tasks waiting on the iterator condition."""
async with self._condition:
self._condition.notify_all()
@dataclasses.dataclass(kw_only=True, slots=True)
class _UploadChunkPart:View on GitHub (pinned to 45b8ed5ab7)
Solutions
- Consume the iterator to completion inside the handler: `async for chunk in it: ...`
- If you must stop early, close/cancel the request so the producer stops pushing
- Inspect the chained task exception to find the root cause in the handler
Example fix
// before
async def handle(it):
first = await it.__anext__()
return process(first) # consumer dies early
// after
async def handle(it):
async for chunk in it:
process(chunk) Defensive patterns
Strategy: try-catch
Try / catch
try:
async for chunk in it:
handle(chunk)
except RuntimeError as e:
log.error("upload consumer died: %s", e.__cause__) Prevention
- Never return from an upload handler before the async for loop completes
- Wrap handler bodies so exceptions drain or cancel the stream
When it happens
Trigger: An async upload handler returns (or raises) without fully draining `async for chunk in upload.iter_chunks()` while the client is still sending data, causing the next push() to detect the dead consumer.
Common situations: Handler returns after reading only the first chunk (e.g. `chunk = await it.__anext__(); return`); handler raises inside the loop; handler task cancelled due to timeout.
Related errors
- Upload chunk iterator is closed.
- @rx.event(background=True) is not supported for upload handl
- `{handler_name}` handler should have a parameter annotated a
- StopAsyncIteration
- Upload event args field is too large.
AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28).
Data as JSON: /api/errors/e0e1ba5a5c09201d.
Report an issue: GitHub.