diff --git a/cognee/api/client.py b/cognee/api/client.py index 6766c12de..fab7f026c 100644 --- a/cognee/api/client.py +++ b/cognee/api/client.py @@ -80,6 +80,26 @@ async def lifespan(app: FastAPI): app = FastAPI(debug=app_environment != "prod", lifespan=lifespan) +@app.middleware("http") +async def log_exceptions_middleware(request: Request, call_next): + try: + return await call_next(request) + except Exception as exc: + logger.error( + f"Unhandled exception in {request.method} {request.url.path}: " + f"{type(exc).__name__}: {str(exc)}" + ) + return JSONResponse( + status_code=500, + content={ + "error": str(exc), + "error_type": type(exc).__name__, + "message": "An internal server error occurred. Please check server logs for details.", + "path": str(request.url.path), + }, + ) + + # Read allowed origins from environment variable (comma-separated) CORS_ALLOWED_ORIGINS = os.getenv("CORS_ALLOWED_ORIGINS") if CORS_ALLOWED_ORIGINS: @@ -169,6 +189,29 @@ async def exception_handler(_: Request, exc: CogneeApiError) -> JSONResponse: return JSONResponse(status_code=status_code, content={"detail": detail["message"]}) +@app.exception_handler(Exception) +async def global_exception_handler(request: Request, exc: Exception) -> JSONResponse: + """ + Global exception handler for all unhandled exceptions. + Logs the full stack trace and returns a 500 error with details. + """ + print(f"🔴 GLOBAL EXCEPTION HANDLER CALLED: {type(exc).__name__}") + logger.exception( + f"Unhandled exception in {request.method} {request.url.path}: " + f"{type(exc).__name__}: {str(exc)}" + ) + + return JSONResponse( + status_code=403, + content={ + "error": str(exc), + "error_type": type(exc).__name__, + "message": "An internal server error occurred. Please check server logs for details.", + "path": request.url.path, + }, + ) + + @app.get("/") async def root(): """ diff --git a/cognee/api/v1/add/routers/get_add_router.py b/cognee/api/v1/add/routers/get_add_router.py index a0649b0f0..1ce363a91 100644 --- a/cognee/api/v1/add/routers/get_add_router.py +++ b/cognee/api/v1/add/routers/get_add_router.py @@ -9,11 +9,8 @@ from cognee.modules.users.models import User from cognee.modules.users.methods import get_authenticated_user from cognee.shared.utils import send_telemetry from cognee.modules.pipelines.models import PipelineRunErrored -from cognee.shared.logging_utils import get_logger from cognee import __version__ as cognee_version -logger = get_logger() - def get_add_router() -> APIRouter: router = APIRouter() @@ -77,31 +74,16 @@ def get_add_router() -> APIRouter: if not datasetId and not datasetName: raise ValueError("Either datasetId or datasetName must be provided.") - try: - add_run = await cognee_add( - data, - datasetName, - user=user, - dataset_id=datasetId, - node_set=node_set if node_set else None, - ) + add_run = await cognee_add( + data, + datasetName, + user=user, + dataset_id=datasetId, + node_set=node_set if node_set else None, + ) - if isinstance(add_run, PipelineRunErrored): - return JSONResponse(status_code=420, content=add_run.model_dump(mode="json")) - return add_run.model_dump() - except Exception as error: - logger.error( - f"Error during add operation for user {user.id}, " - f"dataset: {datasetName or datasetId}, " - f"error type: {type(error).__name__}", - ) - return JSONResponse( - status_code=500, - content={ - "error": str(error), - "error_type": type(error).__name__, - "message": "Failed to add data to dataset", - }, - ) + if isinstance(add_run, PipelineRunErrored): + return JSONResponse(status_code=420, content=add_run.model_dump(mode="json")) + return add_run.model_dump() return router