Skip to content

feat: migrate backend to fastAPI#1005

Merged
lucaseduoli merged 25 commits into
mainfrom
feat/fastapi_transition
Feb 24, 2026
Merged

feat: migrate backend to fastAPI#1005
lucaseduoli merged 25 commits into
mainfrom
feat/fastapi_transition

Conversation

@lucaseduoli

Copy link
Copy Markdown
Collaborator

This pull request updates a core dependency in the project by replacing starlette with fastapi in the pyproject.toml file. This change likely reflects a shift to using FastAPI directly as the main web framework, which is built on top of Starlette and provides additional features for building APIs.

Dependency update:

  • Replaced the starlette dependency with fastapi (version 0.115.0 or higher) in pyproject.toml, indicating a move to use FastAPI as the main framework.

@lucaseduoli lucaseduoli requested a review from phact February 20, 2026 13:26
@lucaseduoli lucaseduoli self-assigned this Feb 20, 2026
@lucaseduoli lucaseduoli linked an issue Feb 20, 2026 that may be closed by this pull request
Comment thread src/api/documents.py Outdated
Comment thread src/api/keys.py Outdated
Comment thread src/api/keys.py Outdated
Comment thread src/api/v1/knowledge_filters.py Outdated
Comment thread src/api/v1/settings.py Outdated
Comment thread src/api/connectors.py
Comment thread src/dependencies.py Outdated

@phact phact left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noticed some bugs

@phact

phact commented Feb 20, 2026

Copy link
Copy Markdown
Collaborator

This would be a good opportunity to expand integration tests to cover auth enabled [cookie + api token]

@edwinjosechittilappilly edwinjosechittilappilly linked an issue Feb 20, 2026 that may be closed by this pull request
3 tasks
@lucaseduoli

Copy link
Copy Markdown
Collaborator Author

This would be a good opportunity to expand integration tests to cover auth enabled [cookie + api token]

I believe we can create those integration tests in another PR. There are other implications for that: we need a google account and a oauth app on the CI for us to test

@lucaseduoli lucaseduoli requested a review from phact February 20, 2026 18:37

@phact phact left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

approved assuming ci passes, recommend expanding unit tests here or in another PR

@edwinjosechittilappilly

Copy link
Copy Markdown
Collaborator

@lucaseduoli Good work!
Also can we mention to the docs about the APIs that are publically (/v1/) available and the one's that are available only to the FE.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request migrates the backend framework from Starlette to FastAPI, introducing dependency injection patterns and Pydantic models for request/response validation.

Changes:

  • Replaced Starlette with FastAPI (version 0.115.0+) in dependencies
  • Created new dependencies.py module with FastAPI dependency injection for services and authentication
  • Refactored all API endpoints to use FastAPI decorators, Pydantic models, and Depends() for dependency injection
  • Added jwt_token field to User dataclass and simplified AnonymousUser to use dataclass defaults

Reviewed changes

Copilot reviewed 30 out of 31 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pyproject.toml Updated dependency from starlette to fastapi
uv.lock Removed Darwin-specific platform markers from fastapi dependencies
src/dependencies.py New module providing FastAPI dependency injection for services and authentication
src/session_manager.py Added jwt_token field to User, refactored AnonymousUser, updated get_user_opensearch_client signature
src/main.py Migrated from Starlette app to FastAPI app with add_api_route instead of Route objects
src/api/*.py Refactored all endpoints to use FastAPI Depends(), Pydantic models, and removed manual request parsing
src/api/v1/*.py Same refactoring for v1 API endpoints
CONTRIBUTING.md Added tip about FastAPI interactive docs at /docs

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/api/settings.py

user = request.state.user
jwt_token = session_manager.get_effective_jwt_token(user.user_id, request.state.jwt_token)
jwt_token = user.jwt_token

Copilot AI Feb 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect indentation for the jwt_token assignment. This line is indented within the previous if block instead of being at the function level. This will cause the jwt_token to not be defined when current_config.edited is True, leading to a NameError.

Copilot uses AI. Check for mistakes.
Comment thread src/api/connectors.py
Comment on lines +759 to +760
connector_type: str,
connection_id: str,

Copilot AI Feb 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing query parameter extraction. The connection_id parameter is declared in the function signature but it's not being extracted from query parameters. In FastAPI, query parameters need to be explicitly defined or extracted. This should use connection_id: str = Query(...) from FastAPI to properly extract the query parameter, or it should be extracted from request.query_params manually.

Copilot uses AI. Check for mistakes.
Comment thread src/api/documents.py
Comment on lines +22 to +23
async def check_filename_exists(
filename: str,

Copilot AI Feb 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Query parameter import. The filename parameter is declared as a simple string parameter, but it's expected to come from query parameters based on the endpoint usage. This should import Query from FastAPI and use filename: str = Query(...) to properly extract the query parameter.

Copilot uses AI. Check for mistakes.
Comment thread src/api/models.py
Comment on lines +84 to +85
async def get_ollama_models(
endpoint: Optional[str] = None,

Copilot AI Feb 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Query parameter import. The endpoint parameter is declared as an optional string parameter, but it's expected to come from query parameters based on the GET method usage. This should import Query from FastAPI and use endpoint: Optional[str] = Query(None) to properly extract the query parameter.

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +19
async def check_provider_health(
provider: Optional[str] = None,
test_completion: bool = False,

Copilot AI Feb 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Query parameter import. The provider and test_completion parameters are declared in the function signature but should come from query parameters based on the GET method usage. These should import Query from FastAPI and use provider: Optional[str] = Query(None) and test_completion: bool = Query(False) to properly extract the query parameters.

Copilot uses AI. Check for mistakes.
Comment thread src/api/settings.py
user = request.state.user
jwt_token = session_manager.get_effective_jwt_token(user.user_id, request.state.jwt_token)
# Get JWT token
jwt_token = user.jwt_token

Copilot AI Feb 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect indentation for the jwt_token assignment. This line is indented too far, making it part of the previous if block instead of being at the function level. This will cause an IndentationError when running the code.

Suggested change
jwt_token = user.jwt_token
jwt_token = user.jwt_token

Copilot uses AI. Check for mistakes.
@edwinjosechittilappilly

Copy link
Copy Markdown
Collaborator

example:
tags=["internal"] and tags=["public"] in add api route

@edwinjosechittilappilly edwinjosechittilappilly left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM awaiting Integration test fix and api tagging.

Comment thread src/api/flows.py
status_code=400
)
logger.error("Invalid request for flow reset", error=str(e))
return JSONResponse({"success": False, "error": str(e)}, status_code=400)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

In general, to fix this kind of problem you should avoid sending raw exception messages or stack traces back to clients. Instead, log the detailed exception information on the server for debugging and observability, and return a generic, user-safe error message in the HTTP response. This preserves developer visibility while preventing attackers from learning about internal implementation details.

In this specific function, the problematic behavior is in the except ValueError as e: block: it logs str(e) (which is fine) and then returns a JSON body whose "error" field is also str(e). To fix this without changing the overall behavior or status codes, we should keep the detailed message in the logs but replace the client-facing error message with a generic description of the problem, such as "Invalid request for flow reset". We should apply the same principle that is already used in the generic Exception handler below, which returns "Internal server error: ..." but should avoid appending str(e) as well (since that also leaks details). However, CodeQL’s alert is specifically for the ValueError block, so we will focus on ensuring that block no longer exposes str(e) and, for consistency and security hardening, also make the generic exception message not include str(e).

Concretely:

  • In src/api/flows.py, in reset_flow_endpoint, update the except ValueError as e: clause so that:
    • Logging remains as-is or is slightly improved (it already logs the error string).
    • The JSON response uses a fixed, generic error message instead of str(e).
  • In the except Exception as e: clause:
    • Keep logging str(e) on the server.
    • Return a fully generic message like "Internal server error" without interpolating str(e) into the response.
      No new imports or helper methods are required; we only adjust the strings passed to JSONResponse.
Suggested changeset 1
src/api/flows.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/flows.py b/src/api/flows.py
--- a/src/api/flows.py
+++ b/src/api/flows.py
@@ -48,10 +48,13 @@
 
     except ValueError as e:
         logger.error("Invalid request for flow reset", error=str(e))
-        return JSONResponse({"success": False, "error": str(e)}, status_code=400)
+        return JSONResponse(
+            {"success": False, "error": "Invalid request for flow reset"},
+            status_code=400,
+        )
     except Exception as e:
         logger.error("Unexpected error in flow reset", error=str(e))
         return JSONResponse(
-            {"success": False, "error": f"Internal server error: {str(e)}"},
-            status_code=500
+            {"success": False, "error": "Internal server error"},
+            status_code=500,
         )
EOF
@@ -48,10 +48,13 @@

except ValueError as e:
logger.error("Invalid request for flow reset", error=str(e))
return JSONResponse({"success": False, "error": str(e)}, status_code=400)
return JSONResponse(
{"success": False, "error": "Invalid request for flow reset"},
status_code=400,
)
except Exception as e:
logger.error("Unexpected error in flow reset", error=str(e))
return JSONResponse(
{"success": False, "error": f"Internal server error: {str(e)}"},
status_code=500
{"success": False, "error": "Internal server error"},
status_code=500,
)
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread src/api/flows.py
"success": False,
"error": f"Internal server error: {str(e)}"
},
{"success": False, "error": f"Internal server error: {str(e)}"},

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

In general, to fix information exposure via exceptions, you should avoid returning raw exception messages or stack traces to clients. Instead, log the detailed exception information server-side (including message and stack trace if desired) and return a generic error message to the user. This preserves debuggability for developers while preventing attackers from learning about internals.

For this specific function in src/api/flows.py, the best fix is to stop including str(e) in the JSON response for the generic except Exception as e: block. We should keep logging the error message (and potentially stack trace) using the existing logger, but the response body should contain a generic message like "Internal server error" without any details from e. We can also slightly improve logging by including exc_info=True so the stack trace is captured in logs, but that’s optional and not required for the fix.

Concretely:

  • In the except Exception as e: block (lines 52–57), keep or improve the logging call but change the JSONResponse payload so that the "error" field is a static string and does not interpolate str(e).
  • Do not change the ValueError handler on lines 49–51, because those messages are generally considered validation/user errors and are already treated as client-facing; the CodeQL alert is specifically about the generic exception handler.
  • No new imports or external libraries are needed; we can rely on the existing logger and JSONResponse.
Suggested changeset 1
src/api/flows.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/flows.py b/src/api/flows.py
--- a/src/api/flows.py
+++ b/src/api/flows.py
@@ -52,6 +52,6 @@
     except Exception as e:
         logger.error("Unexpected error in flow reset", error=str(e))
         return JSONResponse(
-            {"success": False, "error": f"Internal server error: {str(e)}"},
+            {"success": False, "error": "Internal server error"},
             status_code=500
         )
EOF
@@ -52,6 +52,6 @@
except Exception as e:
logger.error("Unexpected error in flow reset", error=str(e))
return JSONResponse(
{"success": False, "error": f"Internal server error: {str(e)}"},
{"success": False, "error": "Internal server error"},
status_code=500
)
Copilot is powered by AI and may make mistakes. Always verify output.
return JSONResponse(
{"error": f"Invalid queryData format: {str(e)}"}, status_code=400
)
return JSONResponse({"error": f"Invalid queryData format: {str(e)}"}, status_code=400)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

In general, to fix information exposure via exceptions, avoid returning raw exception messages or stack traces to clients. Instead, log the detailed error on the server and return a generic, user-friendly message (optionally with a stable error code) that does not contain internal details.

For this specific case, the best fix without changing functionality is to stop including str(e) in the JSON response at line 91. We should keep logging the detailed exception for debugging (logger.error(...)), but the client-facing message should be generic, such as "Invalid queryData format". This preserves behavior (400 status code and indication of what went wrong at a high level) while removing exposure of the underlying exception message.

Concretely:

  • In create_knowledge_filter in src/api/knowledge_filter.py, change the JSONResponse in the except block so that it no longer interpolates e or str(e) into the response.
  • No new imports or helper methods are required; we already log the detailed exception.
Suggested changeset 1
src/api/knowledge_filter.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/knowledge_filter.py b/src/api/knowledge_filter.py
--- a/src/api/knowledge_filter.py
+++ b/src/api/knowledge_filter.py
@@ -88,7 +88,7 @@
         normalized_query_data = normalize_query_data(body.queryData)
     except Exception as e:
         logger.error(f"Failed to normalize query_data: {e}")
-        return JSONResponse({"error": f"Invalid queryData format: {str(e)}"}, status_code=400)
+        return JSONResponse({"error": "Invalid queryData format"}, status_code=400)
 
     jwt_token = user.jwt_token
 
EOF
@@ -88,7 +88,7 @@
normalized_query_data = normalize_query_data(body.queryData)
except Exception as e:
logger.error(f"Failed to normalize query_data: {e}")
return JSONResponse({"error": f"Invalid queryData format: {str(e)}"}, status_code=400)
return JSONResponse({"error": "Invalid queryData format"}, status_code=400)

jwt_token = user.jwt_token

Copilot is powered by AI and may make mistakes. Always verify output.
return JSONResponse(
{"error": f"Invalid queryData format: {str(e)}"}, status_code=400
)
return JSONResponse({"error": f"Invalid queryData format: {str(e)}"}, status_code=400)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

In general, to fix this issue you should avoid returning raw exception messages to the client. Instead, return a generic, user-safe error message, and log the detailed exception on the server side for debugging. This prevents potential leakage of internal details while preserving observability for developers.

For this specific code, the best fix with minimal functional change is to keep logging the detailed error (logger.error(...)) but change the HTTP response so that it does not interpolate str(e). Replace the current JSONResponse({"error": f"Invalid queryData format: {str(e)}"}, status_code=400) with a response that uses a generic message, such as {"error": "Invalid queryData format"}. No new imports are needed; we keep using the existing logger. The change is confined to src/api/knowledge_filter.py around lines 193–197.

Suggested changeset 1
src/api/knowledge_filter.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/knowledge_filter.py b/src/api/knowledge_filter.py
--- a/src/api/knowledge_filter.py
+++ b/src/api/knowledge_filter.py
@@ -194,7 +194,7 @@
         normalized_query_data = normalize_query_data(query_data)
     except Exception as e:
         logger.error(f"Failed to normalize query_data: {e}")
-        return JSONResponse({"error": f"Invalid queryData format: {str(e)}"}, status_code=400)
+        return JSONResponse({"error": "Invalid queryData format"}, status_code=400)
 
     updated_filter = {
         "id": filter_id,
EOF
@@ -194,7 +194,7 @@
normalized_query_data = normalize_query_data(query_data)
except Exception as e:
logger.error(f"Failed to normalize query_data: {e}")
return JSONResponse({"error": f"Invalid queryData format: {str(e)}"}, status_code=400)
return JSONResponse({"error": "Invalid queryData format"}, status_code=400)

updated_filter = {
"id": filter_id,
Copilot is powered by AI and may make mistakes. Always verify output.
return JSONResponse(
{"error": f"Webhook processing failed: {str(e)}"}, status_code=500
)
return JSONResponse({"error": f"Webhook processing failed: {str(e)}"}, status_code=500)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

In general, the fix is to avoid sending raw exception data back to the client and instead return a generic, non-sensitive error message while logging detailed information on the server. Stack traces and exception messages should be captured only in server-side logs.

Concretely in src/api/knowledge_filter.py, within knowledge_filter_webhook, we should:

  • Keep logging the error (ideally including the traceback) using logger.error.
  • Remove the traceback.print_exc() call, which prints to stderr and can leak details in some deployments.
  • Change the JSON response to use a generic error message that does not include str(e) or any internal data.

We can achieve this by:

  • Importing traceback at the top of the file (instead of inside the handler) and using traceback.format_exc() to capture the stack trace as a string, which we then pass to logger.error as structured data.
  • Updating the except block to return something like {"error": "Webhook processing failed"} without interpolating the exception message.

No new functions are required; only modifications within the shown function and an additional import are needed.

Suggested changeset 1
src/api/knowledge_filter.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/knowledge_filter.py b/src/api/knowledge_filter.py
--- a/src/api/knowledge_filter.py
+++ b/src/api/knowledge_filter.py
@@ -9,6 +9,7 @@
 from utils.logging_config import get_logger
 from dependencies import get_knowledge_filter_service, get_monitor_service, get_session_manager, get_current_user
 from session_manager import User
+import traceback
 
 logger = get_logger(__name__)
 
@@ -423,7 +424,9 @@
             filter_id=filter_id,
             subscription_id=subscription_id,
             error=str(e),
+            traceback=traceback.format_exc(),
         )
-        import traceback
-        traceback.print_exc()
-        return JSONResponse({"error": f"Webhook processing failed: {str(e)}"}, status_code=500)
+        return JSONResponse(
+            {"error": "Webhook processing failed"},
+            status_code=500,
+        )
EOF
@@ -9,6 +9,7 @@
from utils.logging_config import get_logger
from dependencies import get_knowledge_filter_service, get_monitor_service, get_session_manager, get_current_user
from session_manager import User
import traceback

logger = get_logger(__name__)

@@ -423,7 +424,9 @@
filter_id=filter_id,
subscription_id=subscription_id,
error=str(e),
traceback=traceback.format_exc(),
)
import traceback
traceback.print_exc()
return JSONResponse({"error": f"Webhook processing failed: {str(e)}"}, status_code=500)
return JSONResponse(
{"error": "Webhook processing failed"},
status_code=500,
)
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread src/api/router.py
error_msg = str(e)
if "AuthenticationException" in error_msg or "access denied" in error_msg.lower():
return JSONResponse({"error": error_msg}, status_code=403)
return JSONResponse({"error": error_msg}, status_code=500)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

In general, to fix this kind of problem you stop sending raw exception messages or stack traces directly to the client. Instead, you log the detailed error (including stack trace) on the server and return a generic, non-sensitive message to the user, optionally with a stable error code they can reference.

For this specific code, the best fix with minimal behavior change is:

  • Keep logging str(e) and the traceback as is.
  • For the generic 500 case, stop returning {"error": error_msg} and instead return a generic message such as {"error": "An internal error has occurred."}.
  • For the special authentication/authorization case, avoid exposing the full raw message. Instead, return a constrained, generic error message (for example, "Authentication failed" or "Access denied") and optionally log the detailed error_msg as is already being done.

Concretely, in src/api/router.py:

  • Replace the 403 branch so that it returns a fixed message, not error_msg.
  • Replace the 500 branch so that it returns a fixed, generic message.

No new imports or helper functions are required; we only adjust the JSONResponse payloads in the except Exception as e: block at the end of _langflow_upload_ingest_task.

Suggested changeset 1
src/api/router.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/router.py b/src/api/router.py
--- a/src/api/router.py
+++ b/src/api/router.py
@@ -168,5 +168,5 @@
         logger.error("Full traceback", traceback=traceback.format_exc())
         error_msg = str(e)
         if "AuthenticationException" in error_msg or "access denied" in error_msg.lower():
-            return JSONResponse({"error": error_msg}, status_code=403)
-        return JSONResponse({"error": error_msg}, status_code=500)
+            return JSONResponse({"error": "Access denied"}, status_code=403)
+        return JSONResponse({"error": "An internal error has occurred."}, status_code=500)
EOF
@@ -168,5 +168,5 @@
logger.error("Full traceback", traceback=traceback.format_exc())
error_msg = str(e)
if "AuthenticationException" in error_msg or "access denied" in error_msg.lower():
return JSONResponse({"error": error_msg}, status_code=403)
return JSONResponse({"error": error_msg}, status_code=500)
return JSONResponse({"error": "Access denied"}, status_code=403)
return JSONResponse({"error": "An internal error has occurred."}, status_code=500)
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread src/api/v1/chat.py
)

logger.error("Failed to list conversations", error=str(e), user_id=user.user_id)
return JSONResponse({"error": f"Failed to list conversations: {str(e)}"}, status_code=500)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

In general, to fix information exposure via exceptions, log the detailed error (and stack trace if desired) on the server, but return only a generic, non-sensitive message to the client. Do not include str(e) or other raw exception data in the API response.

Concretely for this file, we should update all the error-handling branches that currently return responses like {"error": f"...: {str(e)}"} to instead return a constant, generic error message. We will keep the existing logging as-is so that developers still have access to str(e) (and potentially stack traces if configured via logger). This preserves behavior in terms of status codes and high-level semantics while removing sensitive details from the user-visible surface.

Specifically:

  • In chat_list_endpoint (around lines 150–152), keep the logger.error call but change the JSON response to something like {"error": "Failed to list conversations"} without interpolating str(e).
  • In chat_get_endpoint (around lines 194–196), similarly return a generic "Failed to get conversation" message without str(e).
  • In chat_delete_endpoint (around lines 214–216), change the exception handler’s response to a generic "Failed to delete conversation" message.

No new imports or helper methods are required; we only alter the response bodies to remove the embedded exception text.

Suggested changeset 1
src/api/v1/chat.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/v1/chat.py b/src/api/v1/chat.py
--- a/src/api/v1/chat.py
+++ b/src/api/v1/chat.py
@@ -149,7 +149,7 @@
         return JSONResponse({"conversations": conversations})
     except Exception as e:
         logger.error("Failed to list conversations", error=str(e), user_id=user.user_id)
-        return JSONResponse({"error": f"Failed to list conversations: {str(e)}"}, status_code=500)
+        return JSONResponse({"error": "Failed to list conversations"}, status_code=500)
 
 
 async def chat_get_endpoint(
@@ -193,7 +193,7 @@
         })
     except Exception as e:
         logger.error("Failed to get conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
-        return JSONResponse({"error": f"Failed to get conversation: {str(e)}"}, status_code=500)
+        return JSONResponse({"error": "Failed to get conversation"}, status_code=500)
 
 
 async def chat_delete_endpoint(
@@ -213,4 +213,4 @@
             )
     except Exception as e:
         logger.error("Failed to delete conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
-        return JSONResponse({"error": f"Failed to delete conversation: {str(e)}"}, status_code=500)
+        return JSONResponse({"error": "Failed to delete conversation"}, status_code=500)
EOF
@@ -149,7 +149,7 @@
return JSONResponse({"conversations": conversations})
except Exception as e:
logger.error("Failed to list conversations", error=str(e), user_id=user.user_id)
return JSONResponse({"error": f"Failed to list conversations: {str(e)}"}, status_code=500)
return JSONResponse({"error": "Failed to list conversations"}, status_code=500)


async def chat_get_endpoint(
@@ -193,7 +193,7 @@
})
except Exception as e:
logger.error("Failed to get conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
return JSONResponse({"error": f"Failed to get conversation: {str(e)}"}, status_code=500)
return JSONResponse({"error": "Failed to get conversation"}, status_code=500)


async def chat_delete_endpoint(
@@ -213,4 +213,4 @@
)
except Exception as e:
logger.error("Failed to delete conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
return JSONResponse({"error": f"Failed to delete conversation: {str(e)}"}, status_code=500)
return JSONResponse({"error": "Failed to delete conversation"}, status_code=500)
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread src/api/v1/chat.py
user_id = user.user_id
chat_id = request.path_params.get("chat_id")
logger.error("Failed to get conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
return JSONResponse({"error": f"Failed to get conversation: {str(e)}"}, status_code=500)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

In general, to fix information exposure through exceptions, you should avoid including raw exception messages or stack traces in responses sent to clients. Instead, log the detailed error on the server (so developers can debug) and return a generic, non-sensitive error message to the client, possibly with a stable error code if needed.

For this specific code, we should keep logging the exception with context (user_id, chat_id) but change the JSONResponse returned in the except block of chat_get_endpoint to no longer embed str(e). It should return a generic error message such as "Failed to get conversation" and a 500 status code. The logging call can remain as-is, because it is server-side and not exposed to users. We will make a minimal change: only update the response body in the except block of chat_get_endpoint (lines 194–196) in src/api/v1/chat.py. No new imports or helper methods are needed.

Suggested changeset 1
src/api/v1/chat.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/v1/chat.py b/src/api/v1/chat.py
--- a/src/api/v1/chat.py
+++ b/src/api/v1/chat.py
@@ -193,7 +193,7 @@
         })
     except Exception as e:
         logger.error("Failed to get conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
-        return JSONResponse({"error": f"Failed to get conversation: {str(e)}"}, status_code=500)
+        return JSONResponse({"error": "Failed to get conversation"}, status_code=500)
 
 
 async def chat_delete_endpoint(
EOF
@@ -193,7 +193,7 @@
})
except Exception as e:
logger.error("Failed to get conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
return JSONResponse({"error": f"Failed to get conversation: {str(e)}"}, status_code=500)
return JSONResponse({"error": "Failed to get conversation"}, status_code=500)


async def chat_delete_endpoint(
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread src/api/v1/chat.py
status_code=500,
)
logger.error("Failed to delete conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
return JSONResponse({"error": f"Failed to delete conversation: {str(e)}"}, status_code=500)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

In general, to fix this kind of problem, avoid sending raw exception details (messages, stack traces) back to the client. Instead, log the full error details on the server (including the exception and optionally the stack trace) and return a generic, user-safe error message and status code in the HTTP response.

For this specific code, the minimal, non-breaking change is to modify the except block in chat_delete_endpoint so that:

  • The logger.error call continues to record the detailed error on the server (you may keep str(e) there).
  • The JSON response body no longer includes str(e) and instead uses a fixed, generic error message such as "Failed to delete conversation".
  • The HTTP status code remains 500 to preserve behavior, while the response body is sanitized.

No new imports or helper methods are strictly required. We only need to change the return statement within the except block in chat_delete_endpoint in src/api/v1/chat.py to remove the interpolation of str(e).

Suggested changeset 1
src/api/v1/chat.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/v1/chat.py b/src/api/v1/chat.py
--- a/src/api/v1/chat.py
+++ b/src/api/v1/chat.py
@@ -213,4 +213,4 @@
             )
     except Exception as e:
         logger.error("Failed to delete conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
-        return JSONResponse({"error": f"Failed to delete conversation: {str(e)}"}, status_code=500)
+        return JSONResponse({"error": "Failed to delete conversation"}, status_code=500)
EOF
@@ -213,4 +213,4 @@
)
except Exception as e:
logger.error("Failed to delete conversation", error=str(e), user_id=user.user_id, chat_id=chat_id)
return JSONResponse({"error": f"Failed to delete conversation: {str(e)}"}, status_code=500)
return JSONResponse({"error": "Failed to delete conversation"}, status_code=500)
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread src/api/v1/models.py
{"error": f"Failed to retrieve models: {str(e)}"},
status_code=500,
)
return JSONResponse({"error": f"Failed to retrieve models: {str(e)}"}, status_code=500)

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI 4 months ago

To fix the issue, the user-facing error response should not include str(e) (or any detailed exception message). Instead, return a generic, non-sensitive error message, while ensuring the full details are logged on the server for debugging.

The best way to fix this without changing existing functionality is:

  • Keep the logger.error call so that the detailed exception (including its message) is recorded in server logs.
  • Change the JSONResponse body so it no longer interpolates str(e) and instead uses a generic string like "Internal server error while retrieving models.".
  • Optionally, you could include a generic error code or a correlation ID, but that would require additional context not present in the snippet, so we will not introduce that.

Concretely, in src/api/v1/models.py, within list_models_endpoint, update the except Exception as e: block:

  • Leave line 80 (logging) unchanged.
  • Change line 81 to remove str(e) from the error message, returning a fixed, generic error message.

No new imports or helper methods are required.

Suggested changeset 1
src/api/v1/models.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/v1/models.py b/src/api/v1/models.py
--- a/src/api/v1/models.py
+++ b/src/api/v1/models.py
@@ -78,4 +78,4 @@
         return JSONResponse(models)
     except Exception as e:
         logger.error("Failed to list models for provider %s: %s", provider, str(e))
-        return JSONResponse({"error": f"Failed to retrieve models: {str(e)}"}, status_code=500)
+        return JSONResponse({"error": "Failed to retrieve models due to an internal server error."}, status_code=500)
EOF
@@ -78,4 +78,4 @@
return JSONResponse(models)
except Exception as e:
logger.error("Failed to list models for provider %s: %s", provider, str(e))
return JSONResponse({"error": f"Failed to retrieve models: {str(e)}"}, status_code=500)
return JSONResponse({"error": "Failed to retrieve models due to an internal server error."}, status_code=500)
Copilot is powered by AI and may make mistakes. Always verify output.
@edwinjosechittilappilly

Copy link
Copy Markdown
Collaborator

@lucaseduoli good to merge?

@lucaseduoli lucaseduoli merged commit d83cf42 into main Feb 24, 2026
4 checks passed
@edwinjosechittilappilly edwinjosechittilappilly added the enhancement 🔵 New feature or request label Feb 26, 2026
philnash added a commit to philnash/openrag that referenced this pull request Mar 1, 2026
The project moved to FastAPI in PR langflow-ai#1005, this keeps the docs and templates up to date
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement 🔵 New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: [LF] token usage tracking in responses api Swagger.yml to generate API docs

5 participants