psf/requests · error · UnrewindableBodyError

An error occurred when rewinding request body for redirect.

Error message

An error occurred when rewinding request body for redirect.

What it means

Raised by rewind_body() when the request body's seek() method exists and _body_position is recorded, but calling body.seek(position) raises an OSError. This happens during redirect handling when the session tries to rewind a file-like body so it can be re-read for the redirected request. The OSError typically means the underlying file/stream was closed, moved, or is no longer accessible.

Solutions

  1. Read the body into memory before the request: pass data=open(path, 'rb').read() instead of the file object.
  2. Keep the file handle alive for the duration of the request including redirects.
  3. Disable redirects for the initial request and handle them manually, re-opening the file for each attempt.

Example fix

# before
with open('upload.bin', 'rb') as f:
    resp = session.post(url, data=f)  # UnrewindableBodyError on redirect

# after — read into memory
with open('upload.bin', 'rb') as f:
    data = f.read()
resp = session.post(url, data=data)
Defensive patterns

Strategy: fallback

Validate before calling

# Read body into memory before a redirecting request
with open(path, 'rb') as f:
    body = f.read()
resp = session.post(url, data=body)  # bytes are trivially re-readable

Try / catch

try:
    resp = session.post(url, data=file_obj)
except requests.exceptions.UnrewindableBodyError:
    # Fallback: read into memory and retry
    file_obj.seek(0)
    resp = session.post(url, data=file_obj.read(), allow_redirects=True)

Prevention

When it happens

Trigger: A POST/PUT with a file body that gets redirected, but the file handle was closed between the original request and the redirect; a seekable stream whose underlying resource was garbage-collected or closed; a file on a network mount that became unavailable.

Common situations: Uploading a file with redirects enabled where the file handle goes out of scope; using a temporary file that gets cleaned up; streaming from a pipe or subprocess that terminates before the redirect completes; file descriptor limits causing the handle to close.

Related errors


AI-assisted analysis of psf/requests@8068356288 (2026-08-11). Data as JSON: /api/errors/a3498989f4bc6eba. Report an issue: GitHub.

Appendix: source

Thrown at src/requests/utils.py:1151

    netloc = netloc.rsplit("@", 1)[-1]

    return urlunparse((scheme, netloc, path, params, query, ""))


def rewind_body(prepared_request: PreparedRequest) -> None:
    """Move file pointer back to its recorded starting position
    so it can be read again on redirect.
    """
    body_seek = getattr(prepared_request.body, "seek", None)
    if body_seek is not None and isinstance(
        prepared_request._body_position,
        integer_types,
    ):
        try:
            body_seek(prepared_request._body_position)
        except OSError:
            raise UnrewindableBodyError(
                "An error occurred when rewinding request body for redirect."
            )
    else:
        raise UnrewindableBodyError("Unable to rewind request body for redirect.")

View on GitHub (pinned to 8068356288)