fix: abort connection on error preventing infinite build (#6050)

* fix: abort connection on build errors

* fix: streamline error message formatting in ErrorMessage class

* test: remove timeout from waitForSelector in generalBugs-shard-10.spec.ts

---------

Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
anovazzi1 2025-02-03 12:56:26 -03:00 • committed by GitHub
commit d24e989a91
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 643 additions and 32 deletions

View file

@ -389,7 +389,6 @@ async def build_flow(
raise
event_manager.on_vertices_sorted(data={"ids": ids, "to_run": vertices_to_run})
await client_consumed_queue.get()
tasks = []
for vertex_id in ids:
task = asyncio.create_task(build_vertices(vertex_id, graph, client_consumed_queue, event_manager))

View file

@ -368,18 +368,9 @@ class MessageResponse(DefaultModel):
class ErrorMessage(Message):
"""A message class specifically for error messages with predefined error-specific attributes."""
def __init__(
self,
exception: BaseException,
session_id: str | None = None,
source: Source | None = None,
trace_name: str | None = None,
flow_id: UUID | str | None = None,
) -> None:
# This is done to avoid circular imports
if exception.__class__.__name__ == "ExceptionWithMessageError" and exception.__cause__ is not None:
exception = exception.__cause__
# Get the error reason
@staticmethod
def _format_markdown_reason(exception: BaseException) -> str:
"""Format the error reason with markdown formatting."""
reason = f"**{exception.__class__.__name__}**\n"
if hasattr(exception, "body") and isinstance(exception.body, dict) and "message" in exception.body:
reason += f" - **{exception.body.get('message')}**\n"
@ -391,7 +382,37 @@ class ErrorMessage(Message):
reason += f" - **Details:**\n\n```python\n{exception!s}\n```\n"
else:
reason += " - **An unknown error occurred.**\n"
return reason
@staticmethod
def _format_plain_reason(exception: BaseException) -> str:
"""Format the error reason without markdown."""
if hasattr(exception, "body") and isinstance(exception.body, dict) and "message" in exception.body:
reason = f"{exception.body.get('message')}\n"
elif hasattr(exception, "code"):
reason = f"Code: {exception.code}\n"
elif hasattr(exception, "args") and exception.args:
reason = f"{exception.args[0]}\n"
elif isinstance(exception, ValidationError):
reason = f"{exception!s}\n"
else:
reason = "An unknown error occurred.\n"
return reason
def __init__(
self,
exception: BaseException,
session_id: str | None = None,
source: Source | None = None,
trace_name: str | None = None,
flow_id: UUID | str | None = None,
) -> None:
# This is done to avoid circular imports
if exception.__class__.__name__ == "ExceptionWithMessageError" and exception.__cause__ is not None:
exception = exception.__cause__
plain_reason = self._format_plain_reason(exception)
markdown_reason = self._format_markdown_reason(exception)
# Get the sender ID
if trace_name:
match = re.search(r"\((.*?)\)", trace_name)
@ -402,7 +423,7 @@ class ErrorMessage(Message):
session_id=session_id,
sender=source.display_name if source else None,
sender_name=source.display_name if source else None,
text=reason,
text=plain_reason,
properties=Properties(
text_color="red",
background_color="red",
@ -422,7 +443,7 @@ class ErrorMessage(Message):
type="error",
component=source.display_name if source else None,
field=str(exception.field) if hasattr(exception, "field") else None,
reason=reason,
reason=markdown_reason,
solution=str(exception.solution) if hasattr(exception, "solution") else None,
traceback=traceback.format_exc(),
)