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

  1. Consume the iterator to completion inside the handler: `async for chunk in it: ...`
  2. If you must stop early, close/cancel the request so the producer stops pushing
  3. 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

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


AI-assisted analysis of reflex-dev/reflex@45b8ed5ab7 (2026-08-28). Data as JSON: /api/errors/e0e1ba5a5c09201d. Report an issue: GitHub.