improve workflow parameter failure messaging (#4137)
This commit is contained in:
@@ -197,6 +197,14 @@ class MissingValueForParameter(SkyvernHTTPException):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class WorkflowRunParameterPersistenceError(SkyvernException):
|
||||||
|
def __init__(self, parameter_key: str, workflow_id: str, workflow_run_id: str, reason: str) -> None:
|
||||||
|
super().__init__(
|
||||||
|
f"Failed to persist workflow parameter '{parameter_key}' for workflow run {workflow_run_id} "
|
||||||
|
f"of workflow {workflow_id}. Reason: {reason}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class InvalidCredentialId(SkyvernHTTPException):
|
class InvalidCredentialId(SkyvernHTTPException):
|
||||||
def __init__(self, credential_id: str) -> None:
|
def __init__(self, credential_id: str) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ from typing import Any, Literal, cast
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import structlog
|
import structlog
|
||||||
|
from asyncpg.exceptions import NotNullViolationError
|
||||||
|
from sqlalchemy.exc import IntegrityError, SQLAlchemyError
|
||||||
|
|
||||||
import skyvern
|
import skyvern
|
||||||
from skyvern import analytics
|
from skyvern import analytics
|
||||||
@@ -32,6 +34,7 @@ from skyvern.exceptions import (
|
|||||||
WorkflowNotFound,
|
WorkflowNotFound,
|
||||||
WorkflowNotFoundForWorkflowRun,
|
WorkflowNotFoundForWorkflowRun,
|
||||||
WorkflowRunNotFound,
|
WorkflowRunNotFound,
|
||||||
|
WorkflowRunParameterPersistenceError,
|
||||||
)
|
)
|
||||||
from skyvern.forge import app
|
from skyvern.forge import app
|
||||||
from skyvern.forge.prompts import prompt_engine
|
from skyvern.forge.prompts import prompt_engine
|
||||||
@@ -484,19 +487,35 @@ class WorkflowService:
|
|||||||
request_body_value = workflow_request.data[workflow_parameter.key]
|
request_body_value = workflow_request.data[workflow_parameter.key]
|
||||||
if workflow_parameter.workflow_parameter_type == WorkflowParameterType.CREDENTIAL_ID:
|
if workflow_parameter.workflow_parameter_type == WorkflowParameterType.CREDENTIAL_ID:
|
||||||
await self._validate_credential_id(str(request_body_value), organization)
|
await self._validate_credential_id(str(request_body_value), organization)
|
||||||
await self.create_workflow_run_parameter(
|
try:
|
||||||
workflow_run_id=workflow_run.workflow_run_id,
|
await self.create_workflow_run_parameter(
|
||||||
workflow_parameter=workflow_parameter,
|
workflow_run_id=workflow_run.workflow_run_id,
|
||||||
value=request_body_value,
|
workflow_parameter=workflow_parameter,
|
||||||
)
|
value=request_body_value,
|
||||||
|
)
|
||||||
|
except SQLAlchemyError as parameter_error:
|
||||||
|
raise WorkflowRunParameterPersistenceError(
|
||||||
|
parameter_key=workflow_parameter.key,
|
||||||
|
workflow_id=workflow.workflow_permanent_id,
|
||||||
|
workflow_run_id=workflow_run.workflow_run_id,
|
||||||
|
reason=self._format_parameter_persistence_error(parameter_error),
|
||||||
|
) from parameter_error
|
||||||
elif workflow_parameter.default_value is not None:
|
elif workflow_parameter.default_value is not None:
|
||||||
if workflow_parameter.workflow_parameter_type == WorkflowParameterType.CREDENTIAL_ID:
|
if workflow_parameter.workflow_parameter_type == WorkflowParameterType.CREDENTIAL_ID:
|
||||||
await self._validate_credential_id(str(workflow_parameter.default_value), organization)
|
await self._validate_credential_id(str(workflow_parameter.default_value), organization)
|
||||||
await self.create_workflow_run_parameter(
|
try:
|
||||||
workflow_run_id=workflow_run.workflow_run_id,
|
await self.create_workflow_run_parameter(
|
||||||
workflow_parameter=workflow_parameter,
|
workflow_run_id=workflow_run.workflow_run_id,
|
||||||
value=workflow_parameter.default_value,
|
workflow_parameter=workflow_parameter,
|
||||||
)
|
value=workflow_parameter.default_value,
|
||||||
|
)
|
||||||
|
except SQLAlchemyError as parameter_error:
|
||||||
|
raise WorkflowRunParameterPersistenceError(
|
||||||
|
parameter_key=workflow_parameter.key,
|
||||||
|
workflow_id=workflow.workflow_permanent_id,
|
||||||
|
workflow_run_id=workflow_run.workflow_run_id,
|
||||||
|
reason=self._format_parameter_persistence_error(parameter_error),
|
||||||
|
) from parameter_error
|
||||||
else:
|
else:
|
||||||
raise MissingValueForParameter(
|
raise MissingValueForParameter(
|
||||||
parameter_key=workflow_parameter.key,
|
parameter_key=workflow_parameter.key,
|
||||||
@@ -528,6 +547,14 @@ class WorkflowService:
|
|||||||
|
|
||||||
return workflow_run
|
return workflow_run
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _format_parameter_persistence_error(error: SQLAlchemyError) -> str:
|
||||||
|
if isinstance(error, IntegrityError):
|
||||||
|
orig_error = getattr(error, "orig", None)
|
||||||
|
if isinstance(orig_error, NotNullViolationError):
|
||||||
|
return "value cannot be null"
|
||||||
|
return "database error while saving parameter value"
|
||||||
|
|
||||||
async def auto_create_browser_session_if_needed(
|
async def auto_create_browser_session_if_needed(
|
||||||
self,
|
self,
|
||||||
organization_id: str,
|
organization_id: str,
|
||||||
|
|||||||
Reference in New Issue
Block a user