Python: FastAPI error 422 with post request

49,147

Solution 1

Straight from the documentation:

The function parameters will be recognized as follows:

  • If the parameter is also declared in the path, it will be used as a path parameter.
  • If the parameter is of a singular type (like int, float, str, bool, etc) it will be interpreted as a query parameter.
  • If the parameter is declared to be of the type of a Pydantic model, it will be interpreted as a request body."

So to create a POST endpoint that receives a body with a user field you would do something like:

from fastapi import FastAPI
from pydantic import BaseModel


app = FastAPI()


class Data(BaseModel):
    user: str


@app.post("/")
def main(data: Data):
    return data

Solution 2

In my case, I was calling the python API from different python project like this

queryResponse = requests.post(URL, data= query)

I was using the data property, I changed it to json, then it worked for me

queryResponse = requests.post(URL, json = query)

Solution 3

For POST Requests for taking in the request body, you need to do as follows

Create a Pydantic Base Model User

from pydantic import BaseModel

class User(BaseModel):
    user_name: str


@app.post("/")
def main(user: User):
   return user

Solution 4

FastAPI is based on Python type hints so when you pass a query parameter it accepts key:value pair you need to declare it somehow.

Even something like this will work

from typing import Dict, Any
...
@app.post("/")
def main(user: Dict[Any, Any] = None):
    return user

Out: {"user":"Smith"}

But using Pydantic way more effective

class User(BaseModel):
    user: str

@app.post("/")
def main(user: User):
    return user

Out: {"user":"Smith"}

Solution 5

If you're using the fetch API and still getting the 422 Unprocessable Entity, ensure that you have set the Content-Type header:

fetch(someURL, {
  method: "POST",
  headers: {
    "Content-type": "application/json"
  },
  body
}).then(...)

This solved the issue in my case. On the server-side I'm using Pydantic models, so if you aren't using those, see the above answers.

Share:
49,147

Related videos on Youtube

Smith
Author by

Smith

Updated on July 09, 2022

Comments

  • Smith
    Smith almost 2 years

    I'm building a simple API to test a database. When I use get request everything works fine, but if I change to post I get "unprocessable entity" error:

    Here is the FastAPI code:

    from fastapi import FastAPI
    
    app = FastAPI()
    
    @app.post("/")
    def main(user):
        return user
    

    Then, my request using javascript

    let axios = require('axios')
    
    data = { 
        user: 'smith' 
    }
    
    axios.post('http://localhost:8000', data)
        .then(response => (console.log(response.url)))
    

    Also using Python

    import requests
    
    url = 'http://127.0.0.1:8000'
    data = {'user': 'Smith'}
    
    response = requests.post(url, json=data)
    print(response.text)
    

    I also try to parse as json, enconding using utf-8, and change the headers. Nothing has worked for me.

  • Mark Seagoe
    Mark Seagoe over 2 years
    Thanks! This got mine working too... but I still wish I knew why passing a dict via data (like the help file instructs) causes the 422 error status code.
  • Mark Seagoe
    Mark Seagoe over 2 years
    I read that the data field is meant for FormData format... which appears to be a javascript class for passing HTML form data. github.com/tiangolo/fastapi/issues/3373
  • David W.
    David W. over 2 years
    For what it's worth, I didn't start having a problem until I updated fastapi from version 0.63 to 0.70. I was banging my head against the wall until I saw your response. I was originally using jquery in which the "type" was set to "json". I changed my save function to use the fetch api with the Content-type set as you have above and problem solved!
  • Alsushi
    Alsushi over 2 years
    Wow 422 unprocessable entity is a data formating issue after all. The error code and message is not explicit.

Related