fix: make serialization errors in component update show up in the UI (#5332)
* feat: Add SerializationError exception for improved error handling during data serialization - Introduced a new SerializationError class to handle errors when serializing data to JSON. - The class provides detailed error messages based on the type of serialization issue encountered, including async function handling and unsupported object types. - Enhances the robustness of the application by providing clearer feedback for serialization-related errors. * fix: Improve error handling in custom component update to include SerializationError
This commit is contained in:
parent
ae5860e431
commit
0c08bed713
2 changed files with 68 additions and 14 deletions
|
|
@ -7,16 +7,8 @@ from typing import TYPE_CHECKING, Annotated
|
|||
from uuid import UUID
|
||||
|
||||
import sqlalchemy as sa
|
||||
from fastapi import (
|
||||
APIRouter,
|
||||
BackgroundTasks,
|
||||
Body,
|
||||
Depends,
|
||||
HTTPException,
|
||||
Request,
|
||||
UploadFile,
|
||||
status,
|
||||
)
|
||||
from fastapi import APIRouter, BackgroundTasks, Body, Depends, HTTPException, Request, UploadFile, status
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from loguru import logger
|
||||
from sqlmodel import select
|
||||
|
||||
|
|
@ -35,6 +27,7 @@ from langflow.api.v1.schemas import (
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.custom.utils import build_custom_component_template, get_instance_name, update_component_build_config
|
||||
from langflow.exceptions.api import APIException, InvalidChatInputError
|
||||
from langflow.exceptions.serialization import SerializationError
|
||||
from langflow.graph.graph.base import Graph
|
||||
from langflow.graph.schema import RunOutputs
|
||||
from langflow.helpers.flow import get_flow_by_id_or_endpoint_name
|
||||
|
|
@ -46,9 +39,7 @@ from langflow.services.auth.utils import api_key_security, get_current_active_us
|
|||
from langflow.services.cache.utils import save_uploaded_file
|
||||
from langflow.services.database.models.flow import Flow
|
||||
from langflow.services.database.models.flow.model import FlowRead
|
||||
from langflow.services.database.models.flow.utils import (
|
||||
get_all_webhook_components_in_flow,
|
||||
)
|
||||
from langflow.services.database.models.flow.utils import get_all_webhook_components_in_flow
|
||||
from langflow.services.database.models.user.model import User, UserRead
|
||||
from langflow.services.deps import get_session_service, get_settings_service, get_task_service, get_telemetry_service
|
||||
from langflow.services.settings.feature_flags import FEATURE_FLAGS
|
||||
|
|
@ -605,6 +596,9 @@ async def custom_component_update(
|
|||
Returns:
|
||||
dict: The updated custom component node.
|
||||
|
||||
Raises:
|
||||
HTTPException: If there's an error building or updating the component
|
||||
SerializationError: If there's an error serializing the component to JSON
|
||||
"""
|
||||
try:
|
||||
component = Component(_code=code_request.code)
|
||||
|
|
@ -649,7 +643,11 @@ async def custom_component_update(
|
|||
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
return component_node
|
||||
|
||||
try:
|
||||
return jsonable_encoder(component_node)
|
||||
except Exception as exc:
|
||||
raise SerializationError.from_exception(exc, data=component_node) from exc
|
||||
|
||||
|
||||
@router.get("/config", response_model=ConfigResponse)
|
||||
|
|
|
|||
56
src/backend/base/langflow/exceptions/serialization.py
Normal file
56
src/backend/base/langflow/exceptions/serialization.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
from typing import Any
|
||||
|
||||
from fastapi import HTTPException, status
|
||||
|
||||
|
||||
class SerializationError(HTTPException):
|
||||
"""Exception raised when there are errors serializing data to JSON."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
detail: str,
|
||||
original_error: Exception | None = None,
|
||||
data: Any = None,
|
||||
status_code: int = status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
) -> None:
|
||||
super().__init__(status_code=status_code, detail=detail)
|
||||
self.original_error = original_error
|
||||
self.data = data
|
||||
|
||||
@classmethod
|
||||
def from_exception(cls, exc: Exception, data: Any = None) -> "SerializationError":
|
||||
"""Create a SerializationError from an existing exception."""
|
||||
errors = exc.args[0] if exc.args else []
|
||||
|
||||
if isinstance(errors, list):
|
||||
for error in errors:
|
||||
if isinstance(error, TypeError):
|
||||
if "'coroutine'" in str(error):
|
||||
return cls(
|
||||
detail=(
|
||||
"The component contains async functions that need to be awaited. Please add 'await' "
|
||||
"before any async function calls in your component code."
|
||||
),
|
||||
original_error=exc,
|
||||
data=data,
|
||||
)
|
||||
if "vars()" in str(error):
|
||||
return cls(
|
||||
detail=(
|
||||
"The component contains objects that cannot be converted to JSON. Please ensure all "
|
||||
"properties and return values in your component are basic Python types like strings, "
|
||||
"numbers, lists, or dictionaries."
|
||||
),
|
||||
original_error=exc,
|
||||
data=data,
|
||||
)
|
||||
|
||||
# Generic error for other cases
|
||||
return cls(
|
||||
detail=(
|
||||
"The component returned invalid data. Please check that all values in your component (properties, "
|
||||
"return values, etc.) are basic Python types that can be converted to JSON."
|
||||
),
|
||||
original_error=exc,
|
||||
data=data,
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue