{"record":{"id":"0ee2b986c89bea7a","repo":"aio-libs/aiohttp","slug":"bad-content-for-quoted-string-content-r","errorCode":null,"errorMessage":"bad content for quoted-string {content!r}","messagePattern":"bad content for quoted-string (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/helpers.py","lineNumber":412,"sourceCode":"    if name and isinstance(name, str) and name[0] != \"<\" and name[-1] != \">\":\n        return Path(name).name\n    return default\n\n\nnot_qtext_re = re.compile(r\"[^\\041\\043-\\133\\135-\\176]\")\nQCONTENT = {chr(i) for i in range(0x20, 0x7F)} | {\"\\t\"}\n\n\ndef quoted_string(content: str) -> str:\n    \"\"\"Return 7-bit content as quoted-string.\n\n    Format content into a quoted-string as defined in RFC5322 for\n    Internet Message Format. Notice that this is not the 8-bit HTTP\n    format, but the 7-bit email format. Content must be in usascii or\n    a ValueError is raised.\n    \"\"\"\n    if not (QCONTENT > set(content)):\n        raise ValueError(f\"bad content for quoted-string {content!r}\")\n    return not_qtext_re.sub(lambda x: \"\\\\\" + x.group(0), content)\n\n\ndef content_disposition_header(\n    disptype: str,\n    quote_fields: bool = True,\n    _charset: str = \"utf-8\",\n    params: dict[str, str] | None = None,\n) -> str:\n    \"\"\"Sets ``Content-Disposition`` header for MIME.\n\n    This is the MIME payload Content-Disposition header from RFC 2183\n    and RFC 7579 section 4.2, not the HTTP Content-Disposition from\n    RFC 6266.\n\n    disptype is a disposition type: inline, attachment, form-data.\n    Should be valid extension token (see RFC 2183)\n","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/helpers.py#L394-L430","documentation":"quoted_string raises ValueError when the content string contains characters outside the QCONTENT set (printable 7-bit ASCII 0x20-0x7E plus tab). This function formats values as RFC 5322 quoted-strings for Content-Disposition headers, which require 7-bit US-ASCII content.","triggerScenarios":"Calling helpers.quoted_string(content) or indirectly via content_disposition_header when a disposition parameter value contains non-ASCII characters (e.g. Unicode filenames with accented characters, CJK text, emoji) and quote_fields is True.","commonSituations":"Uploading a file with a Unicode name (e.g. 'café.pdf', 'データ.xlsx') as a multipart form field; Content-Disposition parameters with emoji or other non-ASCII content; content_disposition_header called with internationalized filenames.","solutions":["Let content_disposition_header handle it — it catches quoted_string ValueError and falls back to RFC 5987 extended notation (filename* with charset encoding)","If calling quoted_string directly, sanitize content to 7-bit ASCII first","Use the filename* parameter approach: encode non-ASCII filenames with urllib.parse.quote"],"exampleFix":"# before (direct call fails on non-ASCII)\nfrom aiohttp.helpers import quoted_string\nquoted_string('café.pdf')  # ValueError\n\n# after (let content_disposition_header handle encoding)\nfrom aiohttp.helpers import content_disposition_header\nheader = content_disposition_header('attachment', params={'filename': 'café.pdf'})\n# produces: attachment; filename*=utf-8''caf%C3%A9.pdf","handlingStrategy":"validation","validationCode":"QCONTENT = {chr(i) for i in range(0x20, 0x7F)} | {'\\t'}\n\ndef is_quoted_string_safe(content: str) -> bool:\n    return bool(content) and QCONTENT > set(content)\n\nif not is_quoted_string_safe(my_content):\n    # Encode for RFC 5987 extended notation instead\n    from urllib.parse import quote\n    content = f\"utf-8''{quote(my_content, encoding='utf-8')}\"","typeGuard":"def is_ascii_printable(s: str) -> bool:\n    return all(0x20 <= ord(c) <= 0x7E or c == '\\t' for c in s)","tryCatchPattern":"from aiohttp.helpers import quoted_string\ntry:\n    result = quoted_string(content)\nexcept ValueError:\n    from urllib.parse import quote\n    result = f\"utf-8''{quote(content, encoding='utf-8')}\"","preventionTips":["Prefer content_disposition_header() over calling quoted_string() directly — it handles fallback encoding","Sanitize or URL-encode non-ASCII filenames before using them in headers","Test multipart uploads with internationalized filenames"],"tags":["content-disposition","encoding","validation","ascii","rfc-5322"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}