-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Expand file tree
/
Copy patherrors.ts
More file actions
119 lines (100 loc) · 3.36 KB
/
Copy patherrors.ts
File metadata and controls
119 lines (100 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import type { ExecutionContext, ExecutionResult } from '@/executor/types'
import type { SerializedBlock } from '@/serializer/types'
/**
* Interface for errors that carry an ExecutionResult.
* Used when workflow execution fails and we want to preserve partial results.
*/
export interface ErrorWithExecutionResult extends Error {
executionResult: ExecutionResult
}
/**
* Type guard to check if an error carries an ExecutionResult.
* Validates that executionResult has required fields (success, output).
*/
export function hasExecutionResult(error: unknown): error is ErrorWithExecutionResult {
if (
!(error instanceof Error) ||
!('executionResult' in error) ||
error.executionResult == null ||
typeof error.executionResult !== 'object'
) {
return false
}
const result = error.executionResult as Record<string, unknown>
return typeof result.success === 'boolean' && result.output != null
}
/**
* Attaches an ExecutionResult to an error for propagation to parent workflows.
*/
export function attachExecutionResult(error: Error, executionResult: ExecutionResult): void {
Object.assign(error, { executionResult })
}
export interface BlockExecutionErrorDetails {
block: SerializedBlock
error: Error | string
context?: ExecutionContext
additionalInfo?: Record<string, any>
}
export function buildBlockExecutionError(details: BlockExecutionErrorDetails): Error {
const errorMessage =
details.error instanceof Error ? details.error.message : String(details.error)
const blockName = details.block.metadata?.name || details.block.id
const blockType = details.block.metadata?.id || 'unknown'
const error = new Error(`${blockName}: ${errorMessage}`)
const innerStatusCode = readStatusCode(details.error)
Object.assign(error, {
blockId: details.block.id,
blockName,
blockType,
workflowId: details.context?.workflowId,
timestamp: new Date().toISOString(),
...details.additionalInfo,
...(innerStatusCode !== undefined ? { statusCode: innerStatusCode } : {}),
})
return error
}
export function buildHTTPError(config: {
status: number
url?: string
method?: string
message?: string
}): Error {
let errorMessage = config.message || `HTTP ${config.method || 'request'} failed`
if (config.url) {
errorMessage += ` - ${config.url}`
}
if (config.status) {
errorMessage += ` (Status: ${config.status})`
}
const error = new Error(errorMessage)
Object.assign(error, {
status: config.status,
url: config.url,
method: config.method,
timestamp: new Date().toISOString(),
})
return error
}
function readStatusCode(value: unknown): number | undefined {
if (!(value instanceof Error)) return undefined
const status = (value as unknown as { statusCode?: unknown }).statusCode
return typeof status === 'number' ? status : undefined
}
/**
* Maps an execution error to an HTTP status code. Errors thrown from the
* executor that represent workflow-author mistakes (invalid field references,
* etc.) carry a 4xx `statusCode`; everything else is a 500.
*/
export function getExecutionErrorStatus(error: unknown): number {
const status = readStatusCode(error)
if (status !== undefined && status >= 400 && status < 500) {
return status
}
return 500
}
export function normalizeError(error: unknown): string {
if (error instanceof Error) {
return error.message
}
return String(error)
}