aio-libs/aiohttp · error · ValueError
bad content disposition parameter {key!r}={val!r}
Error message
bad content disposition parameter {key!r}={val!r} What it means
Raised by content_disposition_header when a parameter key is empty or contains non-TOKEN characters. Each key (name, filename, etc.) must itself be an RFC 9110 token; values may be quoted/escaped but keys may not.
Source
Thrown at aiohttp/helpers.py:447
Should be valid extension token (see RFC 2183)
quote_fields performs value quoting to 7-bit MIME headers
according to RFC 7578. Set to quote_fields to False if recipient
can take 8-bit file names and field values.
_charset specifies the charset to use when quote_fields is True.
params is a dict with disposition params.
"""
if not disptype or not (TOKEN > set(disptype)):
raise ValueError(f"bad content disposition type {disptype!r}")
value = disptype
if params:
lparams = []
for key, val in params.items():
if not key or not (TOKEN > set(key)):
raise ValueError(f"bad content disposition parameter {key!r}={val!r}")
if quote_fields:
if key.lower() == "filename":
qval = quote(val, "", encoding=_charset)
lparams.append((key, '"%s"' % qval))
else:
try:
qval = quoted_string(val)
except ValueError:
qval = "".join(
(_charset, "''", quote(val, "", encoding=_charset))
)
lparams.append((key + "*", qval))
else:
lparams.append((key, '"%s"' % qval))
else:
qval = val.replace("\\", "\\\\").replace('"', '\\"')
lparams.append((key, '"%s"' % qval))
sparams = "; ".join("=".join(pair) for pair in lparams)View on GitHub (pinned to c0ef574e29)
Solutions
- Use simple token keys: 'name', 'filename', 'size'.
- Sanitize keys: keep only TOKEN characters before calling.
- Validate each key with a TOKEN regex before building params.
Example fix
// before
content_disposition_header('attachment', params={'file name': 'x'})
// after
content_disposition_header('attachment', params={'filename': 'x'}) Defensive patterns
Strategy: validation
Validate before calling
import re
TOKEN_RE = re.compile(r"^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$")
def safe_params(p):
for k in p:
if not TOKEN_RE.fullmatch(k):
raise ValueError(f'bad param key {k!r}')
return p Type guard
def is_valid_param_key(k) -> bool:
import re
return bool(re.fullmatch(r"[!#$%&'*+\-.^_`|~0-9A-Za-z]+", k)) Prevention
- Use simple lowercase token keys (name, filename, size).
- Sanitize dynamic keys to TOKEN characters.
- Never allow empty strings or spaces in parameter keys.
When it happens
Trigger: content_disposition_header('attachment', params={'': 'x'}) (empty key), params={'a b': 'v'} (space in key), params={'na"me': 'v'} (quote in key).
Common situations: Keys derived from user/DB data without sanitization; lowercase/uppercase normalization that introduces illegal chars; copying header snippets that include '=' in keys.
Related errors
- bad content disposition type {disptype!r}
- bad content for quoted-string {content!r}
- Invalid Content-Length header: {content_length_hdr!r}
- Value {value!r} is not a valid etag. Maybe it contains '"'?
- Missing 'Host' header in request.
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/aad668458c493afd.json.
Report an issue: GitHub.