{"record":{"id":"691846c3489052e5","repo":"aio-libs/aiohttp","slug":"data-after-connection-close","errorCode":null,"errorMessage":"Data after `Connection: close`","messagePattern":"Data after `Connection: close`","errorType":"exception","errorClass":"BadHttpMessage","httpStatus":400,"severity":"error","filePath":"aiohttp/http_parser.py","lineNumber":372,"sourceCode":"                    self._max_msg_queue_size\n                    and self._msg_in_flight >= self._max_msg_queue_size\n                ):\n                    # Queue full: buffer the rest and stop. Safe pause point;\n                    # any preceding body is consumed before the next request\n                    # line. Resumes via feed_data(b\"\") when the queue drains.\n                    self._tail = data[start_pos:]\n                    # The remainder now lives in self._tail only. Don't return it.\n                    data = EMPTY\n                    break\n                pos = data.find(SEP, start_pos)\n                # consume \\r\\n\n                if pos == start_pos and not self._lines:\n                    start_pos = pos + len(SEP)\n                    continue\n\n                if pos >= start_pos:\n                    if should_close:\n                        raise BadHttpMessage(\"Data after `Connection: close`\")\n\n                    # line found\n                    line = data[start_pos:pos]\n                    if SEP == b\"\\n\":  # For lax response parsing\n                        line = line.rstrip(b\"\\r\")\n                    if len(line) > max_line_length:\n                        raise LineTooLong(line[:100] + b\"...\", max_line_length)\n\n                    self._lines.append(line)\n                    # After processing the status/request line, everything is a header.\n                    max_line_length = self.max_field_size\n\n                    if len(self._lines) > self.max_headers:\n                        raise BadHttpMessage(\"Too many headers received\")\n\n                    start_pos = pos + len(SEP)\n\n                    # \\r\\n\\r\\n found","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/http_parser.py#L354-L390","documentation":"Raised mid-parse when should_close is set (the peer signalled Connection: close, or another close condition) and additional non-empty lines arrive on the same connection. After a close-framed message the connection must carry nothing more; trailing bytes indicate pipeline injection or a peer that did not honor the close.","triggerScenarios":"A peer sends Connection: close (or triggers should_close) and then keeps writing request lines or data on the same socket.","commonSituations":"HTTP keep-alive confusion, clients pipelining after a close signal, half-closed socket misuse, broken clients that ignore Connection: close.","solutions":["Close the socket immediately after sending/receiving Connection: close.","Do not pipeline further requests after signalling close.","Upgrade the client to honor connection lifecycle semantics."],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"# cannot validate remote bytes; instead, ensure your own client closes after Connection: close\nimport socket\nsock.sendall(req_with_connection_close)\n# read the single response, then:\nsock.shutdown(socket.SHUT_WR)\nsock.close()","typeGuard":"null","tryCatchPattern":"from aiohttp.http_exceptions import BadHttpMessage\ntry:\n    await parser.feed_data(chunk)\nexcept BadHttpMessage as e:\n    # 'Data after Connection: close' -> terminate the transport\n    transport.close()","preventionTips":["Treat Connection: close as terminal: read one message, then close.","Never pipeline after sending close."],"tags":["http","parser","connection","protocol"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}