I have this issue on my QA server, but I was not able to replicate it locally.
My code based on the latest version of https://github.com/tiangolo/full-stack-fastapi-postgresql using the base class in CRUD,
this error happened on the update function
Fatal Python error: Cannot recover from stack overflow.
Thread 0x00007f615d0c0700 (most recent call first):
File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 78 in _worker
File "/usr/local/lib/python3.7/threading.py", line 870 in run
File "/usr/local/lib/python3.7/threading.py", line 926 in _bootstrap_inner
File "/usr/local/lib/python3.7/threading.py", line 890 in _bootstrap
Thread 0x00007f615d8c1700 (most recent call first):
File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 78 in _worker
File "/usr/local/lib/python3.7/threading.py", line 870 in run
File "/usr/local/lib/python3.7/threading.py", line 926 in _bootstrap_inner
File "/usr/local/lib/python3.7/threading.py", line 890 in _bootstrap
Current thread 0x00007f615e19f700 (most recent call first):
File "<string>", line 1 in <lambda>
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/operators.py", line 432 in __getitem__
def update(self, db: Session, *, db_obj: ModelType, obj_in: Union[UpdateSchemaType, Dict[str, Any]]) -> ModelType:
obj_data = jsonable_encoder(db_obj)
if isinstance(obj_in, dict):
update_data = obj_in
else:
update_data = obj_in.dict(exclude_unset=True)
for field in obj_data:
if field in update_data:
setattr(db_obj, field, update_data[field])
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
This was caused by the new release (0.61.0) (jsonable_encoder).
The problem is the line that contains: obj_data = jsonable_encoder(db_obj)
Possible solution:
# Your function
def update(self, db: Session, *, db_obj: ModelType, obj_in: Union[UpdateSchemaType, Dict[str, Any]]) -> ModelType:
obj_data = db_obj.as_dict() # HERE!
if isinstance(obj_in, dict):
update_data = obj_in
else:
update_data = obj_in.dict(exclude_unset=True)
for field in obj_data:
if field in update_data:
setattr(db_obj, field, update_data[field])
db.add(db_obj)
db.commit()
db.refresh(db_obj)
return db_obj
# SQLAlchemy Base object
@as_declarative()
class Base:
def as_dict(self) -> dict:
return {c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs}
But I don't know why we have this error message, I need to check.
EDIT: As reminded by @imadmoussa1:
from sqlalchemy import inspect
I have the same FATAL errors when running normal select statement with databases/encode.
async def list_creators(
skip: int = 0,
limit: int = 0,
manager_id: Optional[int] = None,
mapping_group_id: Optional[int] = None,
):
# basic select statement
base_query = models.Creator.__table__.select()
# if input manager_id
# add where condition of mapping_groups with manager_id
if manager_id:
base_query = base_query.where(
models.Creator.mapping_group_id.in_(
select([column("mapping_group_id")])
.select_from(models.MappingGroupMember.__table__)
.where(models.MappingGroupMember.manager_id == manager_id)
)
)
# if mapping_group_id
# add where condition of mapping_groups with mapping_group_id
if mapping_group_id:
base_query = base_query.where(
models.Creator.mapping_group_id == mapping_group_id
)
# add skip and limit
query = base_query.offset(skip).limit(limit) if limit else base_query.offset(skip)
return await database.fetch_all(query)
@router.get(
"/list",
)
async def read_creators(
skip: int = 0,
limit: int = 100,
manager_id: Optional[int] = None,
mapping_group_id: Optional[int] = None,
):
if manager_id and mapping_group_id:
raise HTTPException(
status_code=400,
detail="Please do not provide manager_id and mapping_group_id at the same time",
)
return await crud.list_creators(
skip=skip, limit=limit, manager_id=manager_id, mapping_group_id=mapping_group_id
)
Any help would be appreciated. This did not happen before.
Same issue here, this crash does not give any trace info, took some time to trace the offending code, as outlined earlier:
https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/crud/base.py#L49
@Kludex Thank you, Your solution fixed my problem.
You're welcome! @imadmoussa1 Do you mind closing the issue then? :sunglasses: :tada:
def as_dict(self) -> dict: return {c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs}
Hi @Kludex
I applied the fix, but it throws me below error:
File ".\crud\base.py", line 49, in update
obj_data = db_obj.as_dict()
File ".\db\base_class.py", line 15, in as_dict
return {c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs}
TypeError: 'module' object is not callable
Hi @sv8083 you should import the inspect from sqlalchemy
from sqlalchemy import inspect
Does it mean jsonable_encoder is broken? It is unclear why the issue was closed.
@plankter jsonable_encoder is not broken, I am using it in different functions, but on update function we had errors. fixed by replacing the jsonable_encoder with a custom function.
This fix does not help in my case, after applying the above fix, I still get the error message:
Fatal Python error: Cannot recover from stack overflow.
Thread 0x00007fa28e7bc700 (most recent call first):
File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 78 in _worker
File "/usr/local/lib/python3.7/threading.py", line 870 in run
File "/usr/local/lib/python3.7/threading.py", line 926 in _bootstrap_inner
File "/usr/local/lib/python3.7/threading.py", line 890 in _bootstrap
Thread 0x00007fa28effd700 (most recent call first):
File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 78 in _worker
File "/usr/local/lib/python3.7/threading.py", line 870 in run
File "/usr/local/lib/python3.7/threading.py", line 926 in _bootstrap_inner
File "/usr/local/lib/python3.7/threading.py", line 890 in _bootstrap
Current thread 0x00007fa28f7fe700 (most recent call first):
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/type_api.py", line 67 in operate
File "<string>", line 1 in <lambda>
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/operators.py", line 432 in __getitem__
File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 762 in operate
Update, fixed my issue:
check_item = crud.item.get_by_user(
db=db, id=item_id, user_id=current_user.id
)
pd_check_item = ItemCheck.from_orm(check_item) # Fix: convert from DB model to pydantic model
check_data = jsonable_encoder(pd_check_item, exclude_none=True) # Breaks if accept db model directly
return check_data
It seems jsonable_encoder can no longer accept a DB model and convert the data, it only accepts a pydantic model.
Another approach I was trying locally was to use load a pydantic model from the orm model, get the dict(), then iterate that, such as:
obj_data = UserInDB.from_orm(db_obj).dict()
...now I know that doesnt perfectly fit into CRUDBase unless we refactor it to also hold onto a DBSchemaType in addition to CreateSchemaType and UpdateSchemaType
This fix does not help in my case, after applying the above fix, I still get the error message:
Fatal Python error: Cannot recover from stack overflow. Thread 0x00007fa28e7bc700 (most recent call first): File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 78 in _worker File "/usr/local/lib/python3.7/threading.py", line 870 in run File "/usr/local/lib/python3.7/threading.py", line 926 in _bootstrap_inner File "/usr/local/lib/python3.7/threading.py", line 890 in _bootstrap Thread 0x00007fa28effd700 (most recent call first): File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 78 in _worker File "/usr/local/lib/python3.7/threading.py", line 870 in run File "/usr/local/lib/python3.7/threading.py", line 926 in _bootstrap_inner File "/usr/local/lib/python3.7/threading.py", line 890 in _bootstrap Current thread 0x00007fa28f7fe700 (most recent call first): File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/type_api.py", line 67 in operate File "<string>", line 1 in <lambda> File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/operators.py", line 432 in __getitem__ File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 762 in operateUpdate, fixed my issue:
check_item = crud.item.get_by_user( db=db, id=item_id, user_id=current_user.id ) pd_check_item = ItemCheck.from_orm(check_item) # Fix: convert from DB model to pydantic model check_data = jsonable_encoder(pd_check_item, exclude_none=True) # Breaks if accept db model directly return check_dataIt seems
jsonable_encodercan no longer accept a DB model and convert the data, it only accepts a pydantic model.
This fix does not help in my case, after applying the above fix, I still get the error message:
Fatal Python error: Cannot recover from stack overflow. Thread 0x00007fa28e7bc700 (most recent call first): File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 78 in _worker File "/usr/local/lib/python3.7/threading.py", line 870 in run File "/usr/local/lib/python3.7/threading.py", line 926 in _bootstrap_inner File "/usr/local/lib/python3.7/threading.py", line 890 in _bootstrap Thread 0x00007fa28effd700 (most recent call first): File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 78 in _worker File "/usr/local/lib/python3.7/threading.py", line 870 in run File "/usr/local/lib/python3.7/threading.py", line 926 in _bootstrap_inner File "/usr/local/lib/python3.7/threading.py", line 890 in _bootstrap Current thread 0x00007fa28f7fe700 (most recent call first): File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/type_api.py", line 67 in operate File "<string>", line 1 in <lambda> File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/operators.py", line 432 in __getitem__ File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 762 in operateUpdate, fixed my issue:
check_item = crud.item.get_by_user( db=db, id=item_id, user_id=current_user.id ) pd_check_item = ItemCheck.from_orm(check_item) # Fix: convert from DB model to pydantic model check_data = jsonable_encoder(pd_check_item, exclude_none=True) # Breaks if accept db model directly return check_dataIt seems
jsonable_encodercan no longer accept a DB model and convert the data, it only accepts a pydantic model.
How to import ItemCheck
How to import ItemCheck
I'm using the project generator, so you can define your own pydantic models like ItemCheck, you can refer to the samples in project generator here:
https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/schemas/item.py#L33
As long as it is based on ItemInDBBase, it will support orm_mode
For me, and also using sqlalchemy, I was simply forgetting to add response_model=schemaName to my endpoint:
Before:
@app.get("/users/me")
async def read_users_me(current_user: schemas.User = Depends(get_current_active_user)):
return current_user
After:
@app.get("/users/me", response_model=schemas.User)
async def read_users_me(current_user: schemas.User = Depends(get_current_active_user)):
return current_user
Thanks for the discussion here everyone! I'm sorry for the inconveniences :facepalm: . This was fixed in 0.61.1. The current latest is 0.62.0.
Most helpful comment
This was caused by the new release (0.61.0) (jsonable_encoder).
The problem is the line that contains:
obj_data = jsonable_encoder(db_obj)Possible solution:
But I don't know why we have this error message, I need to check.
EDIT: As reminded by @imadmoussa1: