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
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.
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
.
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'
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.
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
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.
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
.
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'
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.