aio-libs/aiohttp · error · ValueError

No start or end of range specified

Error message

No start or end of range specified

What it means

When the Range header matches the regex but both captures are empty (e.g. Range: bytes=-), neither start nor end is derivable, so http_range raises ValueError('No start or end of range specified'). It is distinct from the format error: the syntax matched but no usable bound was supplied.

Solutions

  1. Catch ValueError around request.http_range and treat the request as a full-content request.
  2. Respond 416 Range Not Satisfiable if a range is mandatory.
  3. Strip empty Range headers at the reverse proxy.

Example fix

try:
    rng = request.http_range
except ValueError:
    rng = slice(None)   # serve full content
Defensive patterns

Strategy: try-catch

Validate before calling

rng_raw = request.headers.get('Range')
if rng_raw == 'bytes=-':
    rng = slice(None)  # serve full content

Try / catch

try:
    rng = request.http_range
except ValueError:
    rng = slice(None)  # treat as no range

Prevention

When it happens

Trigger: Client sends exactly Range: bytes=- (both start and end blank).

Common situations: Bug in a download manager that constructs Range from empty variables; probing/HEAD-like requests.

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/7bf577f67e583a76. Report an issue: GitHub.

Appendix: source

Thrown at aiohttp/web_request.py:631

                raise ValueError("range not in acceptable format")

            end = int(end) if end else None
            start = int(start) if start else None

            if start is None and end is not None:
                # end with no start is to return tail of content
                start = -end
                end = None

            if start is not None and end is not None:
                # end is inclusive in range header, exclusive for slice
                end += 1

                if start >= end:
                    raise ValueError("start cannot be after end")

            if start is end is None:  # No valid range supplied
                raise ValueError("No start or end of range specified")

        return slice(start, end, 1)

    @reify
    def content(self) -> StreamReader:
        """Return raw payload stream."""
        return self._payload

    @property
    def can_read_body(self) -> bool:
        """Return True if request's HTTP BODY can be read, False otherwise."""
        return not self._payload.at_eof()

    @reify
    def body_exists(self) -> bool:
        """Return True if request has HTTP BODY, False otherwise."""
        return type(self._payload) is not EmptyStreamReader

View on GitHub (pinned to d041d4d0fd)