aio-libs/aiohttp · error · TypeError
content_type must be an instance of str. Got: %s
Error message
content_type must be an instance of str. Got: %s
What it means
Raised by FormData.add_field when content_type is not None but not a str. Content-Type becomes a literal HTTP header value, so non-string types are rejected up front with a TypeError. Setting content_type also forces multipart mode (self._is_multipart = True) after the type check passes.
Source
Thrown at aiohttp/formdata.py:74
) -> None:
if isinstance(value, (io.IOBase, bytes, bytearray, memoryview)):
self._is_multipart = True
_safe_header(name)
type_options: MultiDict[str] = MultiDict({"name": name})
if filename is not None and not isinstance(filename, str):
raise TypeError("filename must be an instance of str. Got: %s" % filename)
if filename is None and isinstance(value, io.IOBase):
filename = guess_filename(value, name)
if filename is not None:
_safe_header(filename)
type_options["filename"] = filename
self._is_multipart = True
headers = {}
if content_type is not None:
if not isinstance(content_type, str):
raise TypeError(
"content_type must be an instance of str. Got: %s" % content_type
)
_safe_header(content_type)
headers[hdrs.CONTENT_TYPE] = content_type
self._is_multipart = True
self._fields.append((type_options, headers, value))
def add_fields(self, *fields: Any) -> None:
to_add: deque[Any] = deque(fields)
while to_add:
rec = to_add.popleft()
if isinstance(rec, io.IOBase):
k = guess_filename(rec, "unknown")
self.add_field(k, rec) # type: ignore[arg-type]
View on GitHub (pinned to c0ef574e29)
Solutions
- Ensure content_type is a plain str or None.
- Guard: content_type=ct if isinstance(ct, str) else None.
- Default to 'application/octet-stream' when mimetypes returns None.
Example fix
// before
ct = mimetypes.guess_type(name)[0]
form.add_field('f', data, content_type=ct)
// after
ct = mimetypes.guess_type(name)[0] or 'application/octet-stream'
form.add_field('f', data, content_type=ct) Defensive patterns
Strategy: type-guard
Validate before calling
def safe_content_type(ct):
if ct is None:
return None
if not isinstance(ct, str):
raise TypeError('content_type must be str')
return ct Type guard
def is_str_or_none(ct) -> bool:
return ct is None or isinstance(ct, str) Prevention
- Default mimetypes.guess_type results to 'application/octet-stream'.
- Never pass tuples or ints as content_type.
- Document content_type as str | None at form-building helpers.
When it happens
Trigger: form.add_field('img', data, content_type=None) is fine, but content_type=123 or a mimetypes.guess_type tuple element used directly fails. Passing a content-type with non-ASCII bytes object also fails.
Common situations: Using mimetypes.guess_type(file)[0] which can return None and then defaulting incorrectly; passing a tuple instead of the string; dynamically building content_type from a lookup dict that returns int codes.
Related errors
- filename must be an instance of str. Got: %s
- Only io.IOBase, multidict and (name, file) pairs allowed, us
- data argument must be str (%r)
- data argument must be byte-ish (%r)
- expected str, got {value!r}
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/ffd4d050ec029d61.json.
Report an issue: GitHub.