{"record":{"id":"244e681f4beadf69","repo":"microsoft/semantic-kernel","slug":"invalid-parameter-types","errorCode":null,"errorMessage":"Invalid parameter types","messagePattern":"Invalid parameter types","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"python/samples/demos/mcp_with_oauth/server/mcp_simple_auth/simple_auth_provider.py","lineNumber":151,"sourceCode":"        </body>\n        </html>\n        \"\"\"\n\n        return HTMLResponse(content=html_content)\n\n    async def handle_login_callback(self, request: Request) -> Response:\n        \"\"\"Handle login form submission callback.\"\"\"\n        form = await request.form()\n        username = form.get(\"username\")\n        password = form.get(\"password\")\n        state = form.get(\"state\")\n\n        if not username or not password or not state:\n            raise HTTPException(400, \"Missing username, password, or state parameter\")\n\n        # Ensure we have strings, not UploadFile objects\n        if not isinstance(username, str) or not isinstance(password, str) or not isinstance(state, str):\n            raise HTTPException(400, \"Invalid parameter types\")\n\n        redirect_uri = await self.handle_simple_callback(username, password, state)\n        return RedirectResponse(url=redirect_uri, status_code=302)\n\n    async def handle_simple_callback(self, username: str, password: str, state: str) -> str:\n        \"\"\"Handle simple authentication callback and return redirect URI.\"\"\"\n        state_data = self.state_mapping.get(state)\n        if not state_data:\n            raise HTTPException(400, \"Invalid state parameter\")\n\n        redirect_uri = state_data[\"redirect_uri\"]\n        code_challenge = state_data[\"code_challenge\"]\n        redirect_uri_provided_explicitly = state_data[\"redirect_uri_provided_explicitly\"] == \"True\"\n        client_id = state_data[\"client_id\"]\n        resource = state_data.get(\"resource\")  # RFC 8707\n\n        # These are required values from our own state mapping\n        assert redirect_uri is not None","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/samples/demos/mcp_with_oauth/server/mcp_simple_auth/simple_auth_provider.py#L133-L169","documentation":"Raised as HTTPException(400) by SimpleAuthProvider.handle_login_callback when username, password, or state are present but not str instances — typically Starlette UploadFile objects from a multipart form with wrong encoding. The handler needs plain string form values.","triggerScenarios":"The form is submitted as multipart/form-data with file inputs, making Starlette return UploadFile objects for username/password/state; a client posts file uploads into text fields; the form's enctype is set to multipart unnecessarily.","commonSituations":"An accidentally added <input type=file>; a testing tool posting multipart bodies; a browser extension altering form encoding; copy-paste introducing a file field.","solutions":["Ensure the login form uses the default application/x-www-form-urlencoded encoding (no enctype=multipart/form-data) and contains no file inputs.","Remove any <input type=file> from the login form.","In tests, post URL-encoded form data, not multipart files.","Optionally read UploadFile values before validation if file uploads are intentional."],"exampleFix":"// before\n<form method=post action=/login/callback enctype=multipart/form-data>\n  <input name=username>\n  ...\n</form>\n\n// after\n<form method=post action=/login/callback>\n  <input name=username>\n  <input name=password type=password>\n  <input type=hidden name=state value=\"{{ state }}\">\n</form>","handlingStrategy":"type-guard","validationCode":"if not all(isinstance(form.get(k), str) for k in ('username','password','state')):\n    raise HTTPException(400, 'Fields must be plain text, not file uploads')\nawait oauth_provider.handle_login_callback(request)","typeGuard":"from starlette.datastructures import UploadFile\n\ndef form_fields_are_strings(form) -> bool:\n    return all(\n        isinstance(form.get(k), str) and not isinstance(form.get(k), UploadFile)\n        for k in ('username', 'password', 'state')\n    )","tryCatchPattern":null,"preventionTips":["Do not set enctype=multipart/form-data on the login form.","Remove any <input type=file> from the form.","In tests, post application/x-www-form-urlencoded bodies."],"tags":["oauth","authentication","mcp","http","forms","type-validation"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}