{"record":{"id":"f78b10ef8a0e6cf7","repo":"aio-libs/aiohttp","slug":"expected-str-got-value-r","errorCode":null,"errorMessage":"expected str, got {value!r}","messagePattern":"expected str, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"aiohttp/formdata.py","lineNumber":112,"sourceCode":"                to_add.extend(rec.items())\n\n            elif isinstance(rec, (list, tuple)) and len(rec) == 2:\n                k, fp = rec\n                self.add_field(k, fp)\n\n            else:\n                raise TypeError(\n                    \"Only io.IOBase, multidict and (name, file) \"\n                    \"pairs allowed, use .add_field() for passing \"\n                    f\"more complex parameters, got {rec!r}\"\n                )\n\n    def _gen_form_urlencoded(self) -> payload.BytesPayload:\n        # form data (x-www-form-urlencoded)\n        data = []\n        for type_options, _, value in self._fields:\n            if not isinstance(value, str):\n                raise TypeError(f\"expected str, got {value!r}\")\n            data.append((type_options[\"name\"], value))\n\n        charset = self._charset if self._charset is not None else \"utf-8\"\n\n        if charset == \"utf-8\":\n            content_type = \"application/x-www-form-urlencoded\"\n        else:\n            content_type = \"application/x-www-form-urlencoded; charset=%s\" % charset\n\n        return payload.BytesPayload(\n            urlencode(data, doseq=True, encoding=charset).encode(),\n            content_type=content_type,\n        )\n\n    def _gen_form_data(self) -> multipart.MultipartWriter:\n        \"\"\"Encode a list of fields using the multipart/form-data MIME format\"\"\"\n        for dispparams, headers, value in self._fields:\n            try:","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/formdata.py#L94-L130","documentation":"FormData._gen_form_urlencoded raises TypeError when generating application/x-www-form-urlencoded body data and a field value is not a str. The urlencoded format only supports string values; binary or file content triggers this error. This fires when is_multipart is False (no files were added) but a non-str value slipped in.","triggerScenarios":"Adding an int, float, bool, bytes, or object value to FormData that will be serialized as urlencoded (no multipart fields present). The error surfaces at serialization time, not at add_field time, because the multipart flag is only set by file/content_type fields.","commonSituations":"Form data with mixed numeric values from a calculation: form.add_field('count', 42); passing a bool value: form.add_field('active', True); passing bytes that were not intended as file content.","solutions":["Convert non-str values to str before adding: form.add_field('count', str(42))","If you have file/binary data, ensure at least one field sets is_multipart (use add_field with a file or content_type to switch to multipart encoding)","Pre-process your data dict to stringify all values"],"exampleFix":"# before\nform.add_field('quantity', 42)\nform.add_field('price', 19.99)\n\n# after\nform.add_field('quantity', str(42))\nform.add_field('price', str(19.99))","handlingStrategy":"validation","validationCode":"def stringify_form_values(fields):\n    \"\"\"Convert all values to str for urlencoded form data.\"\"\"\n    return [(name, str(value) if not isinstance(value, str) else value)\n            for name, value in fields]","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always str() non-string values before adding them to FormData","Use multipart encoding (add a file field) if you have binary data","Type-check form values in a preprocessing step"],"tags":["form-data","type-error","urlencoded","serialization"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}