I am using fastapi along with starlette-admin for my project. when I try to delete an file saved entry from starlette-admin table I get the a large error, this is the last line of the same.
sqlalchemy.exc.InvalidRequestError: This session is in ‘committed’ state; no further SQL can be emitted within this transaction.
I checked the code thoroughly and when I upload file I make sure I commit after i do add but still error occurs
document_data = {
"file_category": file_category,
"file": file_object,
"file_name": updated_name,
"file_size": file_size,
"file_type": file_type,
"upload_timestamp": upload_timestamp,
"uploader_id": current_user.id,
"storage_folder": upload_folder_path,
"file_url": file_url,
}
db_document = UserDocument(**document_data)
db.add(db_document)
db.commit()
db.refresh(db_document)
this is the full error i get
127.0.0.1:40504 – “GET /api/user-document/row-action?name=delete&pk=288 HTTP/1.1” 500
Internal Server Error ERROR: Exception in ASGI application
Traceback (most recent call last): File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/anyio/streams/memory.py”,
line 98, in receive
return self.receive_nowait() File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/anyio/streams/memory.py”,
line 93, in receive_nowait
raise WouldBlock anyio.WouldBlockDuring handling of the above exception, another exception occurred:
Traceback (most recent call last): File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/base.py”,
line 78, in call_next
message = await recv_stream.receive() File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/anyio/streams/memory.py”,
line 118, in receive
raise EndOfStream anyio.EndOfStreamDuring handling of the above exception, another exception occurred:
Traceback (most recent call last): File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/contrib/sqla/middleware.py”,
line 35, in get_session
yield session File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/contrib/sqla/middleware.py”,
line 28, in dispatch
return await call_next(request) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/base.py”,
line 84, in call_next
raise app_exc File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/base.py”,
line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/sessions.py”,
line 86, in call
await self.app(scope, receive, send_wrapper) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/base.py”,
line 108, in call
response = await self.dispatch_func(request, call_next) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/auth.py”,
line 286, in dispatch
return await call_next(request) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/base.py”,
line 84, in call_next
raise app_exc File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/base.py”,
line 70, in coro
await self.app(scope, receive_or_disconnect, send_no_error) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/exceptions.py”,
line 79, in call
raise exc File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/exceptions.py”,
line 68, in call
await self.app(scope, receive, sender) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/routing.py”,
line 718, in call
await route.handle(scope, receive, send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/routing.py”,
line 276, in handle
await self.app(scope, receive, send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/routing.py”,
line 66, in app
response = await func(request) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/base.py”,
line 357, in handle_row_action
handler_return = await model.handle_row_action(request, pk, name) File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/contrib/sqla/view.py”,
line 155, in handle_row_action
return await super().handle_row_action(request, pk, name) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/views.py”,
line 451, in handle_row_action
handler_return = await handler(request, pk) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/views.py”,
line 506, in row_action_3_delete
await self.delete(request, [pk]) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/contrib/sqla/view.py”,
line 453, in delete
await anyio.to_thread.run_sync(session.commit) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/anyio/to_thread.py”,
line 33, in run_sync
return await get_asynclib().run_sync_in_worker_thread( File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/anyio/_backends/_asyncio.py”,
line 877, in run_sync_in_worker_thread
return await future File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/anyio/_backends/_asyncio.py”,
line 807, in run
result = context.run(func, *args) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy/orm/session.py”,
line 1969, in commit
trans.commit(_to_root=True) File “”, line 2, in commit File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy/orm/state_changes.py”,
line 139, in _go
ret_value = fn(self, *arg, **kw) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy/orm/session.py”,
line 1266, in commit
self.session.dispatch.after_commit(self.session) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy/event/attr.py”,
line 378, in call
fn(*args, **kw) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy_file/types.py”,
line 226, in _after_commit
cls.delete_files(getattr(session, “_old_files”, set()), “after_commit”) File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy_file/types.py”,
line 170, in delete_files
StorageManager.delete_file(path) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy_file/storage.py”,
line 138, in delete_file
obj = StorageManager.get(upload_storage).get_object(file_id) File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/libcloud/storage/base.py”,
line 199, in get_object
return self.driver.get_object(container_name=self.name, object_name=object_name) File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/libcloud/storage/drivers/local.py”, line 367, in get_object
return self._make_object(container, object_name) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/libcloud/storage/drivers/local.py”, line 242, in _make_object
raise ObjectDoesNotExistError(value=None, driver=self, object_name=object_name)
libcloud.storage.types.ObjectDoesNotExistError:
<ObjectDoesNotExistError in
<libcloud.storage.drivers.local.LocalStorageDriver object at
0x7f1055c79330>, value=None, object = None>During handling of the above exception, another exception occurred:
Traceback (most recent call last): File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/uvicorn/protocols/http/httptools_impl.py”,
line 426, in run_asgi
result = await app( # type: ignore[func-returns-value] File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/uvicorn/middleware/proxy_headers.py”,
line 84, in call
return await self.app(scope, receive, send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/fastapi/applications.py”,
line 1106, in call
await super().call(scope, receive, send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/applications.py”,
line 122, in call
await self.middleware_stack(scope, receive, send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/errors.py”,
line 184, in call
raise exc File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/errors.py”,
line 162, in call
await self.app(scope, receive, _send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/exceptions.py”,
line 79, in call
raise exc File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/exceptions.py”,
line 68, in call
await self.app(scope, receive, sender) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py”,
line 20, in call
raise e File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/fastapi/middleware/asyncexitstack.py”,
line 17, in call
await self.app(scope, receive, send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/routing.py”,
line 718, in call
await route.handle(scope, receive, send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/routing.py”,
line 443, in handle
await self.app(scope, receive, send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/applications.py”,
line 122, in call
await self.middleware_stack(scope, receive, send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/errors.py”,
line 184, in call
raise exc File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/errors.py”,
line 162, in call
await self.app(scope, receive, _send) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette/middleware/base.py”,
line 108, in call
response = await self.dispatch_func(request, call_next) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/contrib/sqla/middleware.py”,
line 26, in dispatch
with get_session(self.engine) as session: File “/home/user/.pyenv/versions/3.10.13/lib/python3.10/contextlib.py”,
line 153, in exit
self.gen.throw(typ, value, traceback) File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/starlette_admin/contrib/sqla/middleware.py”,
line 37, in get_session
session.rollback() File “/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy/orm/session.py”,
line 1931, in rollback
self._transaction.rollback(_to_root=True) File “”, line 2, in rollback File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy/orm/state_changes.py”,
line 103, in _go
self._raise_for_prerequisite_state(fn.name, current_state) File
“/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/sqlalchemy/orm/session.py”,
line 952, in _raise_for_prerequisite_state
raise sa_exc.InvalidRequestError(
I checked in detail and i think it has to do with how i configured the file upload, as this error occurs at
File "/home/user/.pyenv/versions/3.10.13/envs/virtual_env_name/lib/python3.10/site-packages/libcloud/storage/drivers/local.py", line 242, in _make_object raise ObjectDoesNotExistError(value=None, driver=self, object_name=object_name) libcloud.storage.types.ObjectDoesNotExistError: <ObjectDoesNotExistError in <libcloud.storage.drivers.local.LocalStorageDriver object at 0x7fbdf553e050>, value=None, object = None>
this is how I configured the storage
from sqlalchemy_file.storage import StorageManager
from libcloud.storage.drivers.local import LocalStorageDriver
project_root_folder = settings.PROJECT_FOLDER
file_upload_path = "/backend/app/app/uploads/user_documents"
upload_folder_path = project_root_folder + file_upload_path
os.makedirs(upload_folder_path, 0o777, exist_ok=True)
my_container = LocalStorageDriver(upload_folder_path).get_container("user_documents")
StorageManager.add_storage("user_documents", my_container)
and this is how i used used it in the endpoint
file_object = CustomFile(
content=file_contents, filename=updated_name
)
file_url = generate_file_url(updated_name)
document_data = {
"file_category": file_category,
"file": file_object,
"file_name": updated_name,
"file_size": file_size,
"file_type": file_type,
"upload_timestamp": upload_timestamp,
"uploader_id": current_user.id,
"storage_folder": upload_folder_path,
"file_url": file_url,
}
db_document = UserDocument(**document_data)
db.add(db_document)
db.commit()
db.refresh(db_document)
where CustomFile is
class CustomFile(SQLAlchemyFile):
def get_extension_from_content_type(self) -> Optional[str]:
"""Extract extension from content type."""
if "/" in self.content_type:
_, extension = self.content_type.split("/")
return "." + extension
return None
def save_to_storage(self, upload_storage: Optional[str] = None) -> None:
"""Save current file into provided `upload_storage`."""
extra = self.get("extra", {})
extra.update({"content_type": self.content_type})
metadata = self.get("metadata", None)
if metadata is not None:
warnings.warn(
'metadata attribute is deprecated. Use extra={"meta_data": ...} instead',
DeprecationWarning,
stacklevel=1,
)
extra.update({"meta_data": metadata})
if extra.get("meta_data", None) is None:
extra["meta_data"] = {}
extra["meta_data"].update(
{"filename": self.filename, "content_type": self.content_type}
)
stored_file = self.store_content(
self.original_content,
upload_storage,
extra=extra,
headers=self.get("headers", None),
content_path=self.content_path,
)
self["file_id"] = stored_file.name
self["upload_storage"] = upload_storage
self["uploaded_at"] = datetime.utcnow().isoformat()
self["path"] = f"{upload_storage}/{stored_file.name}"
self["url"] = stored_file.get_cdn_url()
self["saved"] = True
def store_content(
self,
content: Any,
upload_storage: Optional[str] = None,
name: Optional[str] = None,
metadata: Optional[Dict[str, Any]] = None,
extra: Optional[Dict[str, Any]] = None,
headers: Optional[Dict[str, str]] = None,
content_path: Optional[str] = None,
) -> StoredFile:
"""Store content into provided `upload_storage`
with additional `metadata`. Can be used by processors
to store additional files.
"""
stored_file = StorageManager.save_file(
name=extra["meta_data"]["filename"],
content=content,
upload_storage=upload_storage,
metadata=metadata,
extra=extra,
headers=headers,
content_path=content_path,
)
self["files"].append(f"{upload_storage}/{name}")
return stored_file