Textualize/rich · error · ValueError
unable to get the total number of bytes, please specify 'tot
Error message
unable to get the total number of bytes, please specify 'total'
What it means
Progress.wrap_file() needs a total byte count to build a progress bar. It first uses the explicit total= argument, then falls back to the task's existing .total (when task_id= is given). If both are None it raises ValueError telling you to specify 'total'. Unlike Progress.open(), wrap_file does not stat the file for you.
Source
Thrown at rich/progress.py:1267
total (int, optional): Total number of bytes to read. This must be provided unless a task with a total is also given.
task_id (TaskID): Task to track. Default is new task.
description (str, optional): Description of task, if new task is created.
Returns:
BinaryIO: A readable file-like object in binary mode.
Raises:
ValueError: When no total value can be extracted from the arguments or the task.
"""
# attempt to recover the total from the task
total_bytes: Optional[float] = None
if total is not None:
total_bytes = total
elif task_id is not None:
with self._lock:
total_bytes = self._tasks[task_id].total
if total_bytes is None:
raise ValueError(
f"unable to get the total number of bytes, please specify 'total'"
)
# update total of task or create new task
if task_id is None:
task_id = self.add_task(description, total=total_bytes)
else:
self.update(task_id, total=total_bytes)
return _Reader(file, self, task_id, close_handle=False)
@typing.overload
def open(
self,
file: Union[str, "PathLike[str]", bytes],
mode: Literal["rb"],
buffering: int = -1,
encoding: Optional[str] = None,View on GitHub (pinned to 9d8f9a372c)
Solutions
- Pass total= explicitly: progress.wrap_file(file, total=expected_size, task_id=tid).
- If the file is seekable, compute the size yourself: total=f.seek(0, os.SEEK_END); f.seek(0).
- If size is genuinely unknown, use add_task(total=None) with the wrapper omitted — rich renders an indeterminate (spinner) bar — or track completed bytes via progress.update().
Example fix
# before reader = progress.wrap_file(f, task_id=tid) # ValueError: unable to get total # after import os total = os.fstat(f.fileno()).st_size reader = progress.wrap_file(f, total=total, task_id=tid)
Defensive patterns
Strategy: validation
Validate before calling
import os
def wrap_with_total(progress, file, task_id=None, description='Reading'):
total = getattr(file, 'total', None)
if total is None and hasattr(file, 'fileno'):
try:
total = os.fstat(file.fileno()).st_size
except (OSError, ValueError):
total = 0
if total is None:
raise ValueError('cannot determine total size for wrap_file')
return progress.wrap_file(file, total=total, task_id=task_id, description=description) Try / catch
try:
reader = progress.wrap_file(f, task_id=tid)
except ValueError:
# fall back to indeterminate task
tid = progress.add_task('reading', total=None)
reader = f Prevention
- Always pass total= to wrap_file unless you are certain the task already has one.
- Prefer Progress.open() for real files — it stats the size for you.
- For unknown-size streams, use an indeterminate task (total=None) instead of wrap_file.
When it happens
Trigger: progress.wrap_file(file) with no total= and no task_id=; or progress.wrap_file(file, task_id=tid) where the referenced task was created without a total (e.g. add_task('x', total=None) or add_task with start=False and no total). Also when the caller assumed wrap_file would use file size automatically.
Common situations: Streaming a non-seekable object (BytesIO without total, a socket, a generator-backed file-like object) where size is unknowable; migrating from Progress.open() (which stats the file) to wrap_file() and dropping total=; using an indeterminate task and then passing it via task_id=.
Related errors
- invalid mode {mode!r}
- can't have unbuffered text I/O
- invalid value for align, expected "left", "center", or "righ
- invalid value for vertical, expected "top", "middle", or "bo
- level must be 'head', 'row' or 'foot'
AI-assisted analysis of Textualize/rich@9d8f9a372c (2026-08-15).
Data as JSON: /api/errors/de30cb58e78242b1.
Report an issue: GitHub.