urllib3/urllib3 · error · ValueError

body_pos must be of type integer, instead it was {type(body_

Error message

body_pos must be of type integer, instead it was {type(body_pos)}.

What it means

Raised as ValueError from rewind_body() when body_pos is neither an int nor the _FAILEDTELL sentinel (and no seek method exists, or the type simply doesn't match). This is essentially a programming/API-contract error: callers of this internal helper must pass an integer byte offset.

Source

Thrown at src/urllib3/util/request.py:221

    :param int pos:
        Position to seek to in file.
    """
    body_seek = getattr(body, "seek", None)
    if body_seek is not None and isinstance(body_pos, int):
        try:
            body_seek(body_pos)
        except OSError as e:
            raise UnrewindableBodyError(
                "An error occurred when rewinding request body for redirect/retry."
            ) from e
    elif body_pos is _FAILEDTELL:
        raise UnrewindableBodyError(
            "Unable to record file position for rewinding "
            "request body during a redirect/retry."
        )
    else:
        raise ValueError(
            f"body_pos must be of type integer, instead it was {type(body_pos)}."
        )


class ChunksAndContentLength(typing.NamedTuple):
    chunks: typing.Iterable[bytes] | None
    content_length: int | None


def body_to_chunks(
    body: typing.Any | None, method: str, blocksize: int
) -> ChunksAndContentLength:
    """Takes the HTTP request method, body, and blocksize and
    transforms them into an iterable of chunks to pass to
    socket.sendall() and an optional 'Content-Length' header.

    A 'Content-Length' of 'None' indicates the length of the body
    can't be determined so should use 'Transfer-Encoding: chunked'

View on GitHub (pinned to c8d039c1b7)

Solutions

  1. Don't call rewind_body() directly — let urllib3's request machinery manage body positioning during retries/redirects.
  2. If you must, ensure body_pos is an int: rewind_body(body, int(body_pos)).
  3. Validate upstream: if body_pos is None or not isinstance(body_pos, int), skip the rewind path.

Example fix

// before
rewind_body(body, body_pos='0')  # ValueError: body_pos must be of type integer

// after
rewind_body(body, int(body_pos))
Defensive patterns

Strategy: type-guard

Validate before calling

assert isinstance(body_pos, int), f'body_pos must be int, got {type(body_pos)}'

Type guard

from urllib3.util.request import _FAILEDTELL
def is_valid_pos(pos) -> bool:
    return isinstance(pos, int) or pos is _FAILEDTELL

Try / catch

try:
    rewind_body(body, body_pos)
except ValueError:
    rewind_body(body, int(body_pos))

Prevention

When it happens

Trigger: Calling urllib3.util.request.rewind_body() directly with a float, str, None, or other non-int position; passing a stale body_pos that was serialized/deserialized and lost its type; internal bookkeeping that loses the int type.

Common situations: User code reaching into urllib3 internals (rewind_body is module-level) instead of using the public request API; type drift after JSON-serializing request state; monkeypatching that injects a wrong-typed position.

Related errors


AI-assisted analysis of urllib3/urllib3@c8d039c1b7 (2026-08-04). Data as JSON: /data/errors/3b6a4f4fd493451b.json. Report an issue: GitHub.