diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/ai-agent/ai-agent.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/ai-agent/ai-agent.workflow-action.ts index aec6c83273..c5b4dec11c 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/ai-agent/ai-agent.workflow-action.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/ai-agent/ai-agent.workflow-action.ts @@ -7,10 +7,6 @@ import { type Repository } from 'typeorm'; import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; import { AgentAsyncExecutorService } from 'src/engine/metadata-modules/ai/ai-agent-execution/services/agent-async-executor.service'; -import { - AgentException, - AgentExceptionCode, -} from 'src/engine/metadata-modules/ai/ai-agent/agent.exception'; import { AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity'; import { AIBillingService } from 'src/engine/metadata-modules/ai/ai-billing/services/ai-billing.service'; import { DEFAULT_SMART_MODEL } from 'src/engine/metadata-modules/ai/ai-models/constants/ai-models.const'; @@ -56,60 +52,47 @@ export class AiAgentWorkflowAction implements WorkflowAction { const { agentId, prompt } = step.settings.input; const workspaceId = context.workspaceId as string; - try { - let agent: AgentEntity | null = null; + let agent: AgentEntity | null = null; - if (agentId) { - agent = await this.agentRepository.findOne({ - where: { - id: agentId, - workspaceId, - }, - }); - } - - if (agentId && !agent) { - throw new AgentException( - `Agent with id ${agentId} not found`, - AgentExceptionCode.AGENT_NOT_FOUND, - ); - } - - const executionContext = - await this.workflowExecutionContextService.getExecutionContext(runInfo); - - const { result, usage, cacheCreationTokens } = - await this.aiAgentExecutionService.executeAgent({ - agent, - userPrompt: resolveInput(prompt, context) as string, - actorContext: executionContext.isActingOnBehalfOfUser - ? executionContext.initiator - : undefined, - rolePermissionConfig: executionContext.rolePermissionConfig, - authContext: executionContext.authContext, - }); - - await this.aiBillingService.calculateAndBillUsage( - agent?.modelId ?? DEFAULT_SMART_MODEL, - { usage, cacheCreationTokens }, - workspaceId, - agent?.id || null, - ); - - return { - result, - }; - } catch (error) { - if (error instanceof AgentException) { - return { - error: `${error.message} (${error.code})`, - }; - } - - return { - error: - error instanceof Error ? error.message : 'AI Agent execution failed', - }; + if (agentId) { + agent = await this.agentRepository.findOne({ + where: { + id: agentId, + workspaceId, + }, + }); } + + if (agentId && !agent) { + throw new WorkflowStepExecutorException( + `Agent with id ${agentId} not found`, + WorkflowStepExecutorExceptionCode.INVALID_STEP_INPUT, + ); + } + + const executionContext = + await this.workflowExecutionContextService.getExecutionContext(runInfo); + + const { result, usage, cacheCreationTokens } = + await this.aiAgentExecutionService.executeAgent({ + agent, + userPrompt: resolveInput(prompt, context) as string, + actorContext: executionContext.isActingOnBehalfOfUser + ? executionContext.initiator + : undefined, + rolePermissionConfig: executionContext.rolePermissionConfig, + authContext: executionContext.authContext, + }); + + await this.aiBillingService.calculateAndBillUsage( + agent?.modelId ?? DEFAULT_SMART_MODEL, + { usage, cacheCreationTokens }, + workspaceId, + agent?.id || null, + ); + + return { + result, + }; } } diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/code/code.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/code/code.workflow-action.ts index c1d8bf3907..b5189c39ca 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/code/code.workflow-action.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/code/code.workflow-action.ts @@ -4,6 +4,7 @@ import { resolveInput } from 'twenty-shared/utils'; import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; +import { LogicFunctionExecutorService } from 'src/engine/core-modules/logic-function/logic-function-executor/logic-function-executor.service'; import { WorkflowStepExecutorException, WorkflowStepExecutorExceptionCode, @@ -13,7 +14,6 @@ import { type WorkflowActionOutput } from 'src/modules/workflow/workflow-executo import { findStepOrThrow } from 'src/modules/workflow/workflow-executor/utils/find-step-or-throw.util'; import { isWorkflowCodeAction } from 'src/modules/workflow/workflow-executor/workflow-actions/code/guards/is-workflow-code-action.guard'; import { type WorkflowCodeActionInput } from 'src/modules/workflow/workflow-executor/workflow-actions/code/types/workflow-code-action-input.type'; -import { LogicFunctionExecutorService } from 'src/engine/core-modules/logic-function/logic-function-executor/logic-function-executor.service'; @Injectable() export class CodeWorkflowAction implements WorkflowAction { @@ -44,22 +44,18 @@ export class CodeWorkflowAction implements WorkflowAction { context, ) as WorkflowCodeActionInput; - try { - const { workspaceId } = runInfo; + const { workspaceId } = runInfo; - const result = await this.logicFunctionExecutorService.execute({ - logicFunctionId: workflowActionInput.logicFunctionId, - workspaceId, - payload: workflowActionInput.logicFunctionInput, - }); + const result = await this.logicFunctionExecutorService.execute({ + logicFunctionId: workflowActionInput.logicFunctionId, + workspaceId, + payload: workflowActionInput.logicFunctionInput, + }); - if (result.error) { - return { error: result.error.errorMessage }; - } - - return { result: result.data || {} }; - } catch (error) { - return { error: error.message }; + if (result.error) { + return { error: result.error.errorMessage }; } + + return { result: result.data || {} }; } } diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/delay/jobs/resume-delayed-workflow.job.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/delay/jobs/resume-delayed-workflow.job.ts index 2f3c6650ca..2b17874e96 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/delay/jobs/resume-delayed-workflow.job.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/delay/jobs/resume-delayed-workflow.job.ts @@ -103,6 +103,8 @@ export class ResumeDelayedWorkflowJob { ? error.message : `Error during delay resume: ${String(error)}`, }); + + throw error; } }, authContext); } diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/logic-function/logic-function.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/logic-function/logic-function.workflow-action.ts index 91b7a7c050..99a0c7104e 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/logic-function/logic-function.workflow-action.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/logic-function/logic-function.workflow-action.ts @@ -4,6 +4,7 @@ import { resolveInput } from 'twenty-shared/utils'; import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; +import { LogicFunctionExecutorService } from 'src/engine/core-modules/logic-function/logic-function-executor/logic-function-executor.service'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service'; import { @@ -15,7 +16,6 @@ import { type WorkflowActionOutput } from 'src/modules/workflow/workflow-executo import { findStepOrThrow } from 'src/modules/workflow/workflow-executor/utils/find-step-or-throw.util'; import { isWorkflowLogicFunctionAction } from 'src/modules/workflow/workflow-executor/workflow-actions/logic-function/guards/is-workflow-logic-function-action.guard'; import { WorkflowLogicFunctionActionInput } from 'src/modules/workflow/workflow-executor/workflow-actions/logic-function/types/workflow-logic-function-action-input.type'; -import { LogicFunctionExecutorService } from 'src/engine/core-modules/logic-function/logic-function-executor/logic-function-executor.service'; @Injectable() export class LogicFunctionWorkflowAction implements WorkflowAction { @@ -47,42 +47,38 @@ export class LogicFunctionWorkflowAction implements WorkflowAction { context, ) as WorkflowLogicFunctionActionInput; - try { - const { workspaceId } = runInfo; + const { workspaceId } = runInfo; - const { flatLogicFunctionMaps } = - await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( - { - workspaceId, - flatMapsKeys: ['flatLogicFunctionMaps'], - }, - ); + const { flatLogicFunctionMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatLogicFunctionMaps'], + }, + ); - const logicFunction = findFlatEntityByIdInFlatEntityMaps({ - flatEntityId: workflowActionInput.logicFunctionId, - flatEntityMaps: flatLogicFunctionMaps, - }); + const logicFunction = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: workflowActionInput.logicFunctionId, + flatEntityMaps: flatLogicFunctionMaps, + }); - if (!logicFunction) { - throw new WorkflowStepExecutorException( - `Logic function with id ${workflowActionInput.logicFunctionId} not found`, - WorkflowStepExecutorExceptionCode.INVALID_STEP_TYPE, - ); - } - - const result = await this.logicFunctionExecutorService.execute({ - logicFunctionId: workflowActionInput.logicFunctionId, - workspaceId, - payload: workflowActionInput.logicFunctionInput, - }); - - if (result.error) { - return { error: result.error.errorMessage }; - } - - return { result: result.data || {} }; - } catch (error) { - return { error: error.message }; + if (!logicFunction) { + throw new WorkflowStepExecutorException( + `Logic function with id ${workflowActionInput.logicFunctionId} not found`, + WorkflowStepExecutorExceptionCode.INVALID_STEP_TYPE, + ); } + + const result = await this.logicFunctionExecutorService.execute({ + logicFunctionId: workflowActionInput.logicFunctionId, + workspaceId, + payload: workflowActionInput.logicFunctionInput, + }); + + if (result.error) { + return { error: result.error.errorMessage }; + } + + return { result: result.data || {} }; } } diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/create-record.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/create-record.workflow-action.ts index 1c7585d97c..d55a59fc3b 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/create-record.workflow-action.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/create-record.workflow-action.ts @@ -4,10 +4,6 @@ import { resolveInput } from 'twenty-shared/utils'; import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; -import { - RecordCrudException, - RecordCrudExceptionCode, -} from 'src/engine/core-modules/record-crud/exceptions/record-crud.exception'; import { CreateRecordService } from 'src/engine/core-modules/record-crud/services/create-record.service'; import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; import { WorkflowExecutionContextService } from 'src/modules/workflow/workflow-executor/services/workflow-execution-context.service'; @@ -82,10 +78,7 @@ export class CreateRecordWorkflowAction implements WorkflowAction { }); if (!toolOutput.success) { - throw new RecordCrudException( - toolOutput.error || toolOutput.message, - RecordCrudExceptionCode.RECORD_CREATION_FAILED, - ); + return { error: toolOutput.error || toolOutput.message }; } return { diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/delete-record.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/delete-record.workflow-action.ts index a8e858d345..a94b7aefda 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/delete-record.workflow-action.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/delete-record.workflow-action.ts @@ -4,10 +4,6 @@ import { isDefined, isValidUuid, resolveInput } from 'twenty-shared/utils'; import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; -import { - RecordCrudException, - RecordCrudExceptionCode, -} from 'src/engine/core-modules/record-crud/exceptions/record-crud.exception'; import { DeleteRecordService } from 'src/engine/core-modules/record-crud/services/delete-record.service'; import { WorkflowStepExecutorException, @@ -55,9 +51,9 @@ export class DeleteRecordWorkflowAction implements WorkflowAction { !isValidUuid(workflowActionInput.objectRecordId) || !isDefined(workflowActionInput.objectName) ) { - throw new RecordCrudException( + throw new WorkflowStepExecutorException( 'Failed to delete: Object record ID and name are required', - RecordCrudExceptionCode.INVALID_REQUEST, + WorkflowStepExecutorExceptionCode.INVALID_STEP_INPUT, ); } @@ -73,10 +69,7 @@ export class DeleteRecordWorkflowAction implements WorkflowAction { }); if (!toolOutput.success) { - throw new RecordCrudException( - toolOutput.error || toolOutput.message, - RecordCrudExceptionCode.RECORD_DELETION_FAILED, - ); + return { error: toolOutput.error || toolOutput.message }; } return { diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action.ts index 4b2f0586f6..96a12d05b4 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/find-records.workflow-action.ts @@ -12,10 +12,6 @@ import { import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; -import { - RecordCrudException, - RecordCrudExceptionCode, -} from 'src/engine/core-modules/record-crud/exceptions/record-crud.exception'; import { FindRecordsService } from 'src/engine/core-modules/record-crud/services/find-records.service'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; @@ -121,10 +117,7 @@ export class FindRecordsWorkflowAction implements WorkflowAction { }); if (!toolOutput.success) { - throw new RecordCrudException( - toolOutput.error || toolOutput.message, - RecordCrudExceptionCode.QUERY_FAILED, - ); + return { error: toolOutput.error || toolOutput.message }; } const records = toolOutput.result?.records ?? []; diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action.ts index 9e5772c498..2ce5ef240c 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/update-record.workflow-action.ts @@ -4,10 +4,6 @@ import { isDefined, isValidUuid, resolveInput } from 'twenty-shared/utils'; import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; -import { - RecordCrudException, - RecordCrudExceptionCode, -} from 'src/engine/core-modules/record-crud/exceptions/record-crud.exception'; import { UpdateRecordService } from 'src/engine/core-modules/record-crud/services/update-record.service'; import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; import { @@ -79,9 +75,9 @@ export class UpdateRecordWorkflowAction implements WorkflowAction { !isValidUuid(workflowActionInput.objectRecordId) || !isDefined(workflowActionInput.objectName) ) { - throw new RecordCrudException( + throw new WorkflowStepExecutorException( 'Failed to update: Object record ID and name are required', - RecordCrudExceptionCode.INVALID_REQUEST, + WorkflowStepExecutorExceptionCode.INVALID_STEP_INPUT, ); } @@ -96,9 +92,9 @@ export class UpdateRecordWorkflowAction implements WorkflowAction { ); if (filteredFieldsToUpdate?.length === 0) { - throw new RecordCrudException( + throw new WorkflowStepExecutorException( 'Failed to update: No fields to update', - RecordCrudExceptionCode.INVALID_REQUEST, + WorkflowStepExecutorExceptionCode.INVALID_STEP_INPUT, ); } @@ -118,10 +114,7 @@ export class UpdateRecordWorkflowAction implements WorkflowAction { }); if (!toolOutput.success) { - throw new RecordCrudException( - toolOutput.error || toolOutput.message, - RecordCrudExceptionCode.RECORD_UPDATE_FAILED, - ); + return { error: toolOutput.error || toolOutput.message }; } return { diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/upsert-record.workflow-action.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/upsert-record.workflow-action.ts index 4b1d36bf56..a28108b5c5 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/upsert-record.workflow-action.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workflow-actions/record-crud/upsert-record.workflow-action.ts @@ -4,10 +4,6 @@ import { isDefined, resolveInput } from 'twenty-shared/utils'; import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface'; -import { - RecordCrudException, - RecordCrudExceptionCode, -} from 'src/engine/core-modules/record-crud/exceptions/record-crud.exception'; import { UpsertRecordService } from 'src/engine/core-modules/record-crud/services/upsert-record.service'; import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service'; import { @@ -74,9 +70,9 @@ export class UpsertRecordWorkflowAction implements WorkflowAction { ) as WorkflowUpsertRecordActionInput; if (!isDefined(workflowActionInput.objectName)) { - throw new RecordCrudException( + throw new WorkflowStepExecutorException( 'Failed to upsert: Object name is required', - RecordCrudExceptionCode.INVALID_REQUEST, + WorkflowStepExecutorExceptionCode.INVALID_STEP_INPUT, ); } @@ -97,10 +93,7 @@ export class UpsertRecordWorkflowAction implements WorkflowAction { }); if (!toolOutput.success) { - throw new RecordCrudException( - toolOutput.error || toolOutput.message, - RecordCrudExceptionCode.RECORD_UPSERT_FAILED, - ); + return { error: toolOutput.error || toolOutput.message }; } return { diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/__tests__/workflow-executor.workspace-service.spec.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/__tests__/workflow-executor.workspace-service.spec.ts index e93a0f91c6..0bc1e77c14 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/__tests__/workflow-executor.workspace-service.spec.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/__tests__/workflow-executor.workspace-service.spec.ts @@ -14,6 +14,7 @@ import { type WorkflowAction, WorkflowActionType, } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service'; import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service'; @@ -56,6 +57,10 @@ describe('WorkflowExecutorWorkspaceService', () => { canBillMeteredProduct: jest.fn().mockReturnValue(true), }; + const mockExceptionHandlerService = { + captureExceptions: jest.fn(), + }; + const mockMessageQueueService = { add: jest.fn(), }; @@ -84,6 +89,10 @@ describe('WorkflowExecutorWorkspaceService', () => { provide: BillingService, useValue: mockBillingService, }, + { + provide: ExceptionHandlerService, + useValue: mockExceptionHandlerService, + }, { provide: `MESSAGE_QUEUE_${MessageQueue.workflowQueue}`, useValue: mockMessageQueueService, diff --git a/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service.ts b/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service.ts index 6d94d12d61..cafc46064b 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service.ts @@ -15,12 +15,17 @@ import { BillingMeterEventName } from 'src/engine/core-modules/billing/enums/bil import { BillingProductKey } from 'src/engine/core-modules/billing/enums/billing-product-key.enum'; import { BillingService } from 'src/engine/core-modules/billing/services/billing.service'; import { type BillingUsageEvent } from 'src/engine/core-modules/billing/types/billing-usage-event.type'; +import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service'; import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decorators/message-queue.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; import { WorkflowRunStatus } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity'; import { workflowHasRunningSteps } from 'src/modules/workflow/common/utils/workflow-has-running-steps.util'; +import { + WorkflowStepExecutorException, + WorkflowStepExecutorExceptionCode, +} from 'src/modules/workflow/workflow-executor/exceptions/workflow-step-executor.exception'; import { WorkflowActionFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-action.factory'; import { type WorkflowActionOutput } from 'src/modules/workflow/workflow-executor/types/workflow-action-output.type'; import { @@ -51,6 +56,7 @@ export class WorkflowExecutorWorkspaceService { private readonly workspaceEventEmitter: WorkspaceEventEmitter, private readonly workflowRunWorkspaceService: WorkflowRunWorkspaceService, private readonly billingService: BillingService, + private readonly exceptionHandlerService: ExceptionHandlerService, @InjectMessageQueue(MessageQueue.workflowQueue) private readonly messageQueueService: MessageQueueService, ) {} @@ -484,6 +490,18 @@ export class WorkflowExecutorWorkspaceService { }, }); } catch (error) { + const isUserError = + error instanceof WorkflowStepExecutorException && + (error.code === WorkflowStepExecutorExceptionCode.INVALID_STEP_TYPE || + error.code === WorkflowStepExecutorExceptionCode.INVALID_STEP_INPUT || + error.code === WorkflowStepExecutorExceptionCode.STEP_NOT_FOUND); + + if (!isUserError) { + this.exceptionHandlerService.captureExceptions([error], { + workspace: { id: workspaceId }, + }); + } + return { error: error.message ?? 'Execution result error, no data or error', }; diff --git a/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts b/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts index a91d83ad37..9449065da8 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-runner/jobs/run-workflow.job.ts @@ -62,6 +62,8 @@ export class RunWorkflowJob { status: WorkflowRunStatus.FAILED, error: error.message, }); + + throw error; } }, authContext); }