aio-libs/aiohttp · error · ValueError

bad content disposition type

Error message

bad content disposition type {disptype!r}

What it means

content_disposition_header raises ValueError when the disposition type (disptype) is empty or contains characters outside the TOKEN set (RFC 2045 token characters). Valid disposition types include 'inline', 'attachment', 'form-data' — they must be non-empty and contain only token characters (no spaces, semicolons, or control chars).

Solutions

  1. Use a valid disposition type: 'inline', 'attachment', or 'form-data'
  2. Validate the disposition type against TOKEN characters before calling the function
  3. Sanitize user-provided disposition types by stripping invalid characters

Example fix

# before
header = content_disposition_header('')  # ValueError
# or
header = content_disposition_header('attach;ment')  # ValueError

# after
header = content_disposition_header('attachment')
# or validate first
DISPTYPES = {'inline', 'attachment', 'form-data'}
if disptype not in DISPTYPES:
    raise ValueError(f'Invalid disposition type: {disptype}')
Defensive patterns

Strategy: validation

Validate before calling

import re
TOKEN_RE = re.compile(r"^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$")

def validate_disptype(disptype: str) -> str:
    if not disptype or not TOKEN_RE.match(disptype):
        raise ValueError(f'Bad disposition type: {disptype!r}')
    return disptype

Type guard

import re
def is_valid_disposition_type(dt: str) -> bool:
    return bool(dt) and bool(re.match(r"^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$", dt))

Try / catch

try:
    header = content_disposition_header(disptype)
except ValueError as e:
    if 'bad content disposition type' in str(e).lower():
        disptype = 'attachment'  # safe default
        header = content_disposition_header(disptype)
    raise

Prevention

When it happens

Trigger: Calling content_disposition_header('') with an empty string, or passing a disposition type with invalid characters like spaces, semicolons, or non-token separators. Also triggered when set_content_disposition is called on a multipart part with an invalid type.

Common situations: Building Content-Disposition headers dynamically from user input without validation; passing None or empty string as disposition type; typos like 'attach ment' with a space; using a disposition type with special characters.

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/e03301d022a79229. Report an issue: GitHub.

Appendix: source

Thrown at aiohttp/helpers.py:440

    """Sets ``Content-Disposition`` header for MIME.

    This is the MIME payload Content-Disposition header from RFC 2183
    and RFC 7579 section 4.2, not the HTTP Content-Disposition from
    RFC 6266.

    disptype is a disposition type: inline, attachment, form-data.
    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))
                        )

View on GitHub (pinned to d041d4d0fd)