improve workflow parameter failure messaging (#4137)

This commit is contained in:
Celal Zamanoglu
2025-11-29 02:57:20 +03:00
committed by GitHub
parent bd8a3fdfcf
commit 5571662712
2 changed files with 45 additions and 10 deletions

View File

@@ -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__(

View File

@@ -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,