Skip to content

Commit feeb0a8

Browse files
fix(workflow): throw 4xx on variable resolution failures (#4325)
* fix(workflow): throw 4xx on variable resolution failures * Switch spread order
1 parent ceb7d20 commit feeb0a8

5 files changed

Lines changed: 28 additions & 3 deletions

File tree

apps/sim/app/api/workflows/[id]/execute/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ import type {
6161
SerializableExecutionState,
6262
} from '@/executor/execution/types'
6363
import type { NormalizedBlockOutput, StreamingExecution } from '@/executor/types'
64-
import { hasExecutionResult } from '@/executor/utils/errors'
64+
import { getExecutionErrorStatus, hasExecutionResult } from '@/executor/utils/errors'
6565
import { Serializer } from '@/serializer'
6666
import { CORE_TRIGGER_TYPES, type CoreTriggerType } from '@/stores/logs/filters/types'
6767

@@ -821,6 +821,7 @@ async function handleExecutePost(
821821
reqLogger.error(`Non-SSE execution failed: ${errorMessage}`)
822822

823823
const executionResult = hasExecutionResult(error) ? error.executionResult : undefined
824+
const status = getExecutionErrorStatus(error)
824825

825826
return NextResponse.json(
826827
{
@@ -835,7 +836,7 @@ async function handleExecutePost(
835836
}
836837
: undefined,
837838
},
838-
{ status: 500 }
839+
{ status }
839840
)
840841
} finally {
841842
timeoutController.cleanup()

apps/sim/executor/utils/block-reference.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ describe('InvalidFieldError', () => {
293293
expect(error.fieldPath).toBe('invalid.path')
294294
expect(error.availableFields).toEqual(['field1', 'field2'])
295295
expect(error.name).toBe('InvalidFieldError')
296+
expect(error.statusCode).toBe(400)
296297
})
297298

298299
it('should format message correctly', () => {

apps/sim/executor/utils/block-reference.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export interface BlockReferenceResult {
2727
}
2828

2929
export class InvalidFieldError extends Error {
30+
readonly statusCode = 400
31+
3032
constructor(
3133
public readonly blockName: string,
3234
public readonly fieldPath: string,

apps/sim/executor/utils/errors.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,16 @@ export function buildBlockExecutionError(details: BlockExecutionErrorDetails): E
4949

5050
const error = new Error(`${blockName}: ${errorMessage}`)
5151

52+
const innerStatusCode = readStatusCode(details.error)
53+
5254
Object.assign(error, {
5355
blockId: details.block.id,
5456
blockName,
5557
blockType,
5658
workflowId: details.context?.workflowId,
5759
timestamp: new Date().toISOString(),
5860
...details.additionalInfo,
61+
...(innerStatusCode !== undefined ? { statusCode: innerStatusCode } : {}),
5962
})
6063

6164
return error
@@ -89,6 +92,25 @@ export function buildHTTPError(config: {
8992
return error
9093
}
9194

95+
function readStatusCode(value: unknown): number | undefined {
96+
if (!(value instanceof Error)) return undefined
97+
const status = (value as unknown as { statusCode?: unknown }).statusCode
98+
return typeof status === 'number' ? status : undefined
99+
}
100+
101+
/**
102+
* Maps an execution error to an HTTP status code. Errors thrown from the
103+
* executor that represent workflow-author mistakes (invalid field references,
104+
* etc.) carry a 4xx `statusCode`; everything else is a 500.
105+
*/
106+
export function getExecutionErrorStatus(error: unknown): number {
107+
const status = readStatusCode(error)
108+
if (status !== undefined && status >= 400 && status < 500) {
109+
return status
110+
}
111+
return 500
112+
}
113+
92114
export function normalizeError(error: unknown): string {
93115
if (error instanceof Error) {
94116
return error.message

apps/sim/executor/variables/resolvers/block.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ export class BlockResolver implements Resolver {
9797
if (fallback !== undefined) {
9898
return fallback
9999
}
100-
throw new Error(error.message)
101100
}
102101
throw error
103102
}

0 commit comments

Comments
 (0)