psf/requests · error · TypeError

chunk_size must be an int, it is instead a {type(chunk_size)

Error message

chunk_size must be an int, it is instead a {type(chunk_size)}.

What it means

A `TypeError` raised by `Response.iter_content` when `chunk_size` is neither None nor an int. The chunk size is handed to `self.raw.read(chunk_size)` / `iter_slices`, which require an integer; the explicit guard produces a clear message instead of a confusing failure deep inside urllib3. It exists as a runtime check for untyped callers.

Source

Thrown at src/requests/models.py:963

                    raise ConnectionError(e)
                except SSLError as e:
                    raise RequestsSSLError(e)
            else:
                # Standard file-like object.
                while True:
                    chunk = self.raw.read(chunk_size)
                    if not chunk:
                        break
                    yield chunk

            self._content_consumed = True

        if self._content_consumed and isinstance(self._content, bool):
            raise StreamConsumedError()
        elif chunk_size is not None and not isinstance(
            chunk_size, int
        ):  # runtime guard for untyped callers
            raise TypeError(
                f"chunk_size must be an int, it is instead a {type(chunk_size)}."
            )

        if self._content_consumed:
            # simulate reading small chunks of the content
            content = cast(bytes, self._content)
            chunks = iter_slices(content, chunk_size)
        else:
            chunks = generate()

        if decode_unicode:
            chunks = stream_decode_response_unicode(chunks, self)

        return chunks

    @overload
    def iter_lines(
        self,

View on GitHub ↗ (pinned to 414f0513c3)

Solutions

  1. Convert the value to int before the call: `resp.iter_content(chunk_size=int(cfg['chunk_size']))`.
  2. If the value comes from division, use integer division: `chunk_size = total // parts`.
  3. Use keyword arguments (`chunk_size=`, `decode_unicode=`) to avoid positional mix-ups.

Example fix

# before
chunk = os.environ.get('CHUNK_SIZE', '8192')
for part in resp.iter_content(chunk_size=chunk): ...

# after
chunk = int(os.environ.get('CHUNK_SIZE', '8192'))
for part in resp.iter_content(chunk_size=chunk): ...
Defensive patterns

Strategy: type-guard

Validate before calling

if chunk_size is not None and not isinstance(chunk_size, int):
    chunk_size = int(chunk_size)

Type guard

def valid_chunk_size(cs):
    return cs is None or (isinstance(cs, int) and not isinstance(cs, bool) and cs > 0)

Try / catch

try:
    for chunk in resp.iter_content(chunk_size=chunk_size):
        ...
except TypeError:
    # chunk_size was a str/float (e.g. from config); coerce to int and retry once
    raise

Prevention

When it happens

Trigger: `resp.iter_content(chunk_size='1024')` (string from config/CLI parsing), `chunk_size=1024.0` (float from arithmetic like `size/8`), or any non-int passed positionally: `resp.iter_content('1024')`. Also indirectly via `iter_lines(chunk_size=...)`, which forwards the value.

Common situations: Chunk size read from an env var, argparse without `type=int`, or a YAML/JSON config as a string; computing chunk size with `/` (true division yields float) instead of `//`; accidentally passing `decode_unicode` or another argument positionally into the chunk_size slot.

Related errors


AI-assisted analysis of psf/requests@414f0513c3 (2026-07-31). Data as JSON: /data/errors/c4770f35686c4dc8.json. Report an issue: GitHub ↗.