{"record":{"id":"e7f97e93bd3ac5a4","repo":"aio-libs/aiohttp","slug":"range-not-in-acceptable-format","errorCode":null,"errorMessage":"range not in acceptable format","messagePattern":"range not in acceptable format","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/web_request.py","lineNumber":613,"sourceCode":"        parsed = parse_cookie_header(self.headers.get(hdrs.COOKIE, \"\"))\n        # Extract values from Morsel objects\n        return MappingProxyType({name: morsel.value for name, morsel in parsed})\n\n    @reify\n    def http_range(self) -> \"slice[int, int, int]\":\n        \"\"\"The content of Range HTTP header.\n\n        Return a slice instance.\n\n        \"\"\"\n        rng = self._headers.get(hdrs.RANGE)\n        start, end = None, None\n        if rng is not None:\n            try:\n                pattern = r\"^bytes=(\\d*)-(\\d*)$\"\n                start, end = re.findall(pattern, rng, re.ASCII)[0]\n            except IndexError:  # pattern was not found in header\n                raise ValueError(\"range not in acceptable format\")\n\n            end = int(end) if end else None\n            start = int(start) if start else None\n\n            if start is None and end is not None:\n                # end with no start is to return tail of content\n                start = -end\n                end = None\n\n            if start is not None and end is not None:\n                # end is inclusive in range header, exclusive for slice\n                end += 1\n\n                if start >= end:\n                    raise ValueError(\"start cannot be after end\")\n\n            if start is end is None:  # No valid range supplied\n                raise ValueError(\"No start or end of range specified\")","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/web_request.py#L595-L631","documentation":"The http_range property parses the Range header with the strict regex ^bytes=(\\d*)-(\\d*)$. If the header is present but does not match (re.findall returns no capture group, raising IndexError), aiohttp raises ValueError('range not in acceptable format'). This indicates a syntactically invalid Range from the client.","triggerScenarios":"Range: items=0-100 (wrong unit), Range: bytes=abc-def (non-numeric), Range: 0-100 (missing 'bytes='), Range: bytes=1-2,3-4 (multiple ranges unsupported).","commonSituations":"Misbehaving crawlers/clients; custom download managers; CDNs forwarding non-standard Range syntax.","solutions":["Catch ValueError around access to request.http_range and respond 416 Range Not Satisfiable.","On invalid range, fall back to serving the full file (ignore the header).","Document to clients that only single-range bytes= syntax is accepted."],"exampleFix":"# before\nrng = request.http_range   # raises on bad header\n# after\ntry:\n    rng = request.http_range\nexcept ValueError:\n    raise web.HTTPRequestRangeNotSatisfiable()","handlingStrategy":"try-catch","validationCode":"import re\nrng = request.headers.get('Range')\nif rng is not None and not re.match(r'^bytes=\\d*-\\d*$', rng):\n    raise web.HTTPRequestRangeNotSatisfiable()","typeGuard":null,"tryCatchPattern":"try:\n    rng = request.http_range\nexcept ValueError:\n    raise web.HTTPRequestRangeNotSatisfiable()","preventionTips":["Always wrap request.http_range access in try/except ValueError.","Decide upfront: ignore invalid Range or respond 416.","Log malformed Range headers to spot misbehaving clients."],"tags":["range","validation","fileresponse","http-header"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}