Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions apps/sim/app/api/workflows/[id]/execute/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,10 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:

return NextResponse.json(filteredResult)
} catch (error: any) {
logger.error(`[${requestId}] Non-SSE execution failed:`, error)
// Block errors are already logged with full details by BlockExecutor
// Only log the error message here to avoid duplicate logging
const errorMessage = error.message || 'Unknown error'
logger.error(`[${requestId}] Non-SSE execution failed: ${errorMessage}`)

const executionResult = error.executionResult

Expand Down Expand Up @@ -803,7 +806,10 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
},
})
} catch (error: any) {
logger.error(`[${requestId}] SSE execution failed:`, error)
// Block errors are already logged with full details by BlockExecutor
// Only log the error message here to avoid duplicate logging
const errorMessage = error.message || 'Unknown error'
logger.error(`[${requestId}] SSE execution failed: ${errorMessage}`)

const executionResult = error.executionResult

Expand All @@ -813,7 +819,7 @@ export async function POST(req: NextRequest, { params }: { params: Promise<{ id:
executionId,
workflowId,
data: {
error: executionResult?.error || error.message || 'Unknown error',
error: executionResult?.error || errorMessage,
duration: executionResult?.metadata?.duration || 0,
},
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,16 +244,11 @@ export function Panel() {
shortcut: 'Mod+Enter',
allowInEditable: false,
handler: () => {
try {
if (isExecuting) {
cancelWorkflow()
} else if (!isButtonDisabled) {
runWorkflow()
} else {
logger.warn('Cannot run workflow: button is disabled')
}
} catch (err) {
logger.error('Failed to execute Cmd+Enter command', { err })
// Do exactly what the Run button does
if (isExecuting) {
cancelWorkflow()
} else {
runWorkflow()
}
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { WorkflowValidationError } from '@/serializer'
import { useExecutionStore } from '@/stores/execution/store'
import { useVariablesStore } from '@/stores/panel/variables/store'
import { useEnvironmentStore } from '@/stores/settings/environment/store'
import { useTerminalConsoleStore } from '@/stores/terminal'
import { type ConsoleEntry, useTerminalConsoleStore } from '@/stores/terminal'
import { useWorkflowDiffStore } from '@/stores/workflow-diff'
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
import { mergeSubblockState } from '@/stores/workflows/utils'
Expand Down Expand Up @@ -1005,21 +1005,31 @@ export function useWorkflowExecution() {
logs: [],
}

// Add error to console
addConsole({
input: {},
output: {},
success: false,
error: data.error,
durationMs: data.duration || 0,
startedAt: new Date(Date.now() - (data.duration || 0)).toISOString(),
endedAt: new Date().toISOString(),
workflowId: activeWorkflowId,
blockId: 'workflow',
executionId: executionId || uuidv4(),
blockName: 'Workflow Execution',
blockType: 'workflow',
})
// Only add workflow-level error if no blocks have executed yet
// This catches pre-execution errors (validation, serialization, etc.)
// Block execution errors are already logged via onBlockError callback
const { entries } = useTerminalConsoleStore.getState()
const existingLogs = entries.filter(
(log: ConsoleEntry) => log.executionId === executionId
)

if (existingLogs.length === 0) {
// No blocks executed yet - this is a pre-execution error
addConsole({
input: {},
output: {},
success: false,
error: data.error,
durationMs: data.duration || 0,
startedAt: new Date(Date.now() - (data.duration || 0)).toISOString(),
endedAt: new Date().toISOString(),
workflowId: activeWorkflowId,
blockId: 'validation',
executionId: executionId || uuidv4(),
blockName: 'Workflow Validation',
blockType: 'validation',
})
}
},
},
})
Expand Down
15 changes: 12 additions & 3 deletions apps/sim/executor/execution/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,13 @@ export class ExecutionEngine {
logs: this.context.blockLogs,
metadata: this.context.metadata,
}
const executionError = new Error(errorMessage)
;(executionError as any).executionResult = executionResult
throw executionError

// Attach executionResult to the original error instead of creating a new one
// This preserves block error metadata (blockId, blockName, blockType, etc.)
if (error && typeof error === 'object') {
;(error as any).executionResult = executionResult
}
throw error
}
}

Expand Down Expand Up @@ -105,6 +109,11 @@ export class ExecutionEngine {

private trackExecution(promise: Promise<void>): void {
this.executing.add(promise)
// Attach error handler to prevent unhandled rejection warnings
// The actual error handling happens in waitForAllExecutions/waitForAnyExecution
promise.catch(() => {
// Error will be properly handled by Promise.all/Promise.race in wait methods
})
promise.finally(() => {
this.executing.delete(promise)
})
Expand Down