{"record":{"id":"4ebdcc16d0a59897","repo":"aio-libs/aiohttp","slug":"boundary-value-contains-invalid-characters","errorCode":null,"errorMessage":"boundary value contains invalid characters","messagePattern":"boundary value contains invalid characters","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/multipart.py","lineNumber":992,"sourceCode":"        # Refer to RFCs 7231, 7230, 5234.\n        #\n        # parameter      = token \"=\" ( token / quoted-string )\n        # token          = 1*tchar\n        # quoted-string  = DQUOTE *( qdtext / quoted-pair ) DQUOTE\n        # qdtext         = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text\n        # obs-text       = %x80-FF\n        # quoted-pair    = \"\\\" ( HTAB / SP / VCHAR / obs-text )\n        # tchar          = \"!\" / \"#\" / \"$\" / \"%\" / \"&\" / \"'\" / \"*\"\n        #                  / \"+\" / \"-\" / \".\" / \"^\" / \"_\" / \"`\" / \"|\" / \"~\"\n        #                  / DIGIT / ALPHA\n        #                  ; any VCHAR, except delimiters\n        # VCHAR           = %x21-7E\n        value = self._boundary\n        if re.match(self._valid_tchar_regex, value):\n            return value.decode(\"ascii\")  # cannot fail\n\n        if re.search(self._invalid_qdtext_char_regex, value):\n            raise ValueError(\"boundary value contains invalid characters\")\n\n        # escape %x5C and %x22\n        quoted_value_content = value.replace(b\"\\\\\", b\"\\\\\\\\\")\n        quoted_value_content = quoted_value_content.replace(b'\"', b'\\\\\"')\n\n        return '\"' + quoted_value_content.decode(\"ascii\") + '\"'\n\n    @property\n    def boundary(self) -> str:\n        return self._boundary.decode(\"ascii\")\n\n    def append(self, obj: Any, headers: Mapping[str, str] | None = None) -> Payload:\n        if headers is None:\n            headers = CIMultiDict()\n\n        if isinstance(obj, Payload):\n            obj.headers.update(headers)\n            return self.append_payload(obj)","sourceCodeStart":974,"sourceCodeEnd":1010,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/multipart.py#L974-L1010","documentation":"The _boundary_value property formats the boundary for the Content-Type header. If the bytes are not a bare token (matching the tchar regex) AND they contain a character invalid even inside a quoted-string (matched by _invalid_qdtext_char_regex), ValueError is raised because the value cannot be serialized either as a token or as a quoted string.","triggerScenarios":"A boundary containing control characters, NUL, bare backslash sequences that break quoted-string rules, or other bytes outside the union of tchar and valid qdtext/obs-text.","commonSituations":"User-supplied boundaries with whitespace, control chars, or delimiters; binary boundaries not filtered through the bchars set; boundaries copied from opaque tokens.","solutions":["Restrict boundaries to RFC 2046 bchars: A-Za-z0-9 and '()+,-./_:;=?\\''.","Let MultipartWriter autogenerate the boundary.","Sanitize the candidate boundary: re.sub(r'[^A-Za-z0-9\\'()+,-./_:;=?]', '', value).","Unit-test boundary serialization by constructing the writer and reading its Content-Type header."],"exampleFix":"// before\nmw = MultipartWriter(boundary='my boundary with space')\n\n// after\nmw = MultipartWriter(boundary='my_boundary_with_underscore')","handlingStrategy":"validation","validationCode":"import re\n_VALID_BOUNDARY = re.compile(r\"[A-Za-z0-9'()+,./_:;=?-]+\\Z\")\n\ndef is_serializable_boundary(value: str) -> bool:\n    return bool(_VALID_BOUNDARY.match(value))","typeGuard":"import re\n_TOKEN = re.compile(r\"[A-Za-z0-9'()+,./_:;=?-]+\\Z\")\ndef is_token_boundary(value: object) -> bool:\n    return isinstance(value, str) and bool(_TOKEN.match(value))","tryCatchPattern":"try:\n    mw = MultipartWriter(boundary=candidate)\n    _ = mw.content_type  # forces _boundary_value formatting\nexcept ValueError as e:\n    if 'invalid characters' in str(e):\n        mw = MultipartWriter()  # fall back to safe autogenerated boundary\n    else:\n        raise","preventionTips":["Restrict boundaries to RFC 2046 bchars to guarantee both token and quoted-string serializability.","Avoid whitespace, control chars, backslashes, and quote characters in boundaries.","Let MultipartWriter autogenerate the boundary."],"tags":["multipart","boundary","validation","rfc-2046","content-type","writer"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}