{"record":{"id":"1c2dd7d5de19f6ed","repo":"aio-libs/aiohttp","slug":"filename-must-be-an-instance-of-str-got-s","errorCode":null,"errorMessage":"filename must be an instance of str. Got: %s","messagePattern":"filename must be an instance of str\\. Got: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"aiohttp/formdata.py","lineNumber":63,"sourceCode":"    @property\n    def is_multipart(self) -> bool:\n        return self._is_multipart\n\n    def add_field(\n        self,\n        name: str,\n        value: Any,\n        *,\n        content_type: str | None = None,\n        filename: str | None = None,\n    ) -> None:\n        if isinstance(value, (io.IOBase, bytes, bytearray, memoryview)):\n            self._is_multipart = True\n\n        _safe_header(name)\n        type_options: MultiDict[str] = MultiDict({\"name\": name})\n        if filename is not None and not isinstance(filename, str):\n            raise TypeError(\"filename must be an instance of str. Got: %s\" % filename)\n        if filename is None and isinstance(value, io.IOBase):\n            filename = guess_filename(value, name)\n        if filename is not None:\n            _safe_header(filename)\n            type_options[\"filename\"] = filename\n            self._is_multipart = True\n\n        headers = {}\n        if content_type is not None:\n            if not isinstance(content_type, str):\n                raise TypeError(\n                    \"content_type must be an instance of str. Got: %s\" % content_type\n                )\n            _safe_header(content_type)\n            headers[hdrs.CONTENT_TYPE] = content_type\n            self._is_multipart = True\n\n        self._fields.append((type_options, headers, value))","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/formdata.py#L45-L81","documentation":"FormData.add_field raises TypeError when the filename keyword argument is not None and not a str instance. The filename is used in the Content-Disposition header of the multipart part, so it must be a plain string. This is a type validation guard, not a runtime I/O error.","triggerScenarios":"Calling form.add_field('file', data, filename=Path('photo.jpg')) or passing an int, bytes, or other non-str value as the filename argument. Common when using pathlib.Path objects or os.path.join results without converting to str.","commonSituations":"Passing a pathlib.Path object directly as filename; using os.path.basename which may return bytes on some systems; passing an integer or float from a computed filename.","solutions":["Convert the filename to str: form.add_field('file', data, filename=str(my_path))","If using pathlib.Path, call .name then str(): filename=str(path.name)","Ensure the filename comes from a string source, not bytes or Path"],"exampleFix":"# before\nfrom pathlib import Path\nform.add_field('upload', f, filename=Path('/tmp/photo.jpg'))\n\n# after\nform.add_field('upload', f, filename=str(Path('/tmp/photo.jpg').name))","handlingStrategy":"type-guard","validationCode":"def coerce_filename(fn):\n    if fn is None:\n        return None\n    if isinstance(fn, bytes):\n        return fn.decode('utf-8')\n    if not isinstance(fn, str):\n        return str(fn)\n    return fn\n\nform.add_field('file', data, filename=coerce_filename(my_filename))","typeGuard":"def is_valid_filename(fn) -> bool:\n    return fn is None or isinstance(fn, str)","tryCatchPattern":"try:\n    form.add_field('file', data, filename=fn)\nexcept TypeError as e:\n    if 'filename must be an instance of str' in str(e):\n        form.add_field('file', data, filename=str(fn))\n    raise","preventionTips":["Always wrap pathlib.Path filenames with str() before passing to add_field","Use static type checking (mypy) to catch non-str filename arguments at lint time"],"tags":["form-data","type-error","multipart","validation"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}