FastApi: 422 Unprocessable Entity

Question:

I’m getting this error while trying to accept a pedantic model. After debugging for quite some time I believe the problem is with accepting CodeCreate

Pydantic model

class BaseCode(BaseModel):
    index: Optional[int] = Field(None)
    email: EmailStr
    gen_time: datetime
    expire_time: datetime


class CodeCreate(BaseCode):
    code: int
    used_time: Optional[datetime] = Field(None)

    class Config:
        orm_mode = True

class Message(BaseModel):
    message: str

Code ORM

class Code(Base):
    __tablename__ = 'code'

    index = Column(Integer, primary_key=True, autoincrement=True)
    code = Column(Integer)
    email = Column(String, ForeignKey('user.email'))
    gen_time = Column(DateTime)
    expire_time = Column(DateTime)
    used_time = Column(DateTime, nullable=True)

Handler

@app.post('/verify-code', response_model=schemas.Message, responses={404: {"model": schemas.Message}, 406: {"model": schemas.Message}})
async def verify_code(code: schemas.CodeCreate, response: Response, device_name: str = Body(..., embed=True), db=Depends(get_db)):

    result = crud.verify_and_insert_code(db=db, code=code)
    if result == 'matched':
        response.status_code = status.HTTP_202_ACCEPTED
        return crud.start_new_session(db=db, session=schemas.Session(session_id='1234', start_time=datetime.now(), email=code.email, device_name=device_name))
    elif result == 'not-matched':
        response.status_code = status.HTTP_200_OK
    elif result == 'expire':
        response.status_code = status.HTTP_406_NOT_ACCEPTABLE
    elif result == 'invalid':
        response.status_code = status.HTTP_404_NOT_FOUND

    return schemas.Message(message="Item not found")

Body of request from the client

{
  "code": {
    "index": 0,
    "email": "[email protected]",
    "gen_time": "2022-01-24T16:38:12.612Z",
    "expire_time": "2022-01-24T16:38:12.612Z",
    "code": 0,
    "used_time": "2022-01-24T16:38:12.612Z"
  },
  "device_name": "string"
}

Response body for 422

{
  "detail": [
    {
      "loc": [
        "body",
        "code",
        "email"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    },
    {
      "loc": [
        "body",
        "code",
        "gen_time"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    },
    {
      "loc": [
        "body",
        "code",
        "expire_time"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    },
    {
      "loc": [
        "body",
        "code",
        "code"
      ],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

Temporary Solution

Removing this ORM confirmation code from Pydantic model solves the issue. I believe there might be a clash between CodeCreate pydantic model and Code ORM model, but I don’t know how to resolve it.

class Config:
    orm_mode = True
Asked By: ASAD HAMEED

||

Answers:

According to MDN
here,
a 422 Unprocessable Entity means that the information of the request could not be processed.

In this case, the most likely problem is that the data of the POST request that is sent does not match with the Pydantic model.

Make sure the data that is sent is in the correct format.

Answered By: user18013439

Just as stated above by Brian Law, your request body is in the form of Code, which is not a pydantic model, but a database one.

When you send the POST request, the body should match up with CodeCreate, not Code.

Answered By: Brian

Found the solution after debugging for quite a while.

The ORM configured pedantic model can’t be used to receive requests from the client.

In my case, I had to create another class that extends the CodeCreate class add ORM configuration to that class and use CodeCreate for body from the client.

class BaseCode(BaseModel):
    index: Optional[int] = Field(None)
    email: EmailStr
    gen_time: datetime
    expire_time: datetime


class CodeCreate(BaseCode):
    code: int
    used_time: Optional[datetime] = Field(None)

    
class Code(CodeCreate):

    class Config:
            orm_mode = True

Post request

@app.post('/verify-code')
async def verify_code(code: schemas.CodeCreate):
    return 'success'
Answered By: ASAD HAMEED

The 422 Unprocessable Entity error because of ContentType is incorrect. The FastAPI/Pydantic need ContentType = application/json to parse request body.

Are you sure your POST request has ContentType header is application/json?

If not add it!

Ensure that you have provided content type in your request,

xhr.setRequestHeader('Content-Type', 'application/json')

If it’s there, then verify the format of your input. Here, you have declared four varibales – index, gen_time, email and expire_time.

Important: You might provide a default value for these files in FastAPI. In that case, if you provided an empty content or null as the attribute values then the fastapi will throw the above error.

Ensure that the data that you are sending to the server is correct.

Answered By: Codemaker