Skip to content

Commit b549ee4

Browse files
waleedlatif1claude
andcommitted
fix(brightdata): return error objects instead of throwing in postProcess
The executor wraps postProcess in try-catch and falls back to the intermediate transformResponse result on error, which has success: true with empty results. Throwing errors would silently return empty results. Match Firecrawl's pattern: return { ...result, success: false, error } instead of throwing. Also add taskId to BrightDataDiscoverResponse type to eliminate unsafe casts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 17827e8 commit b549ee4

File tree

2 files changed

+74
-42
lines changed

2 files changed

+74
-42
lines changed

apps/sim/tools/brightdata/discover.ts

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -106,71 +106,102 @@ export const brightDataDiscoverTool: ToolConfig<
106106
totalResults: 0,
107107
taskId: data.task_id ?? null,
108108
},
109-
} as BrightDataDiscoverResponse
109+
}
110110
},
111111

112112
postProcess: async (result, params) => {
113113
if (!result.success) return result
114114

115-
const taskId = (result.output as Record<string, unknown>).taskId as string | null
115+
const taskId = result.output.taskId
116116
if (!taskId) {
117-
throw new Error('Discover API did not return a task_id. Cannot poll for results.')
117+
return {
118+
...result,
119+
success: false,
120+
error: 'Discover API did not return a task_id. Cannot poll for results.',
121+
}
118122
}
119123

120124
logger.info(`Bright Data Discover task ${taskId} created, polling for results...`)
121125

122126
let elapsedTime = 0
123127

124128
while (elapsedTime < MAX_POLL_TIME_MS) {
125-
const pollResponse = await fetch(
126-
`https://api.brightdata.com/discover?task_id=${encodeURIComponent(taskId)}`,
127-
{
128-
method: 'GET',
129-
headers: {
130-
Authorization: `Bearer ${params.apiKey}`,
131-
},
129+
try {
130+
const pollResponse = await fetch(
131+
`https://api.brightdata.com/discover?task_id=${encodeURIComponent(taskId)}`,
132+
{
133+
method: 'GET',
134+
headers: {
135+
Authorization: `Bearer ${params.apiKey}`,
136+
},
137+
}
138+
)
139+
140+
if (!pollResponse.ok) {
141+
return {
142+
...result,
143+
success: false,
144+
error: `Failed to poll discover results: ${pollResponse.statusText}`,
145+
}
132146
}
133-
)
134-
135-
if (!pollResponse.ok) {
136-
throw new Error(`Failed to poll discover results: ${pollResponse.statusText}`)
137-
}
138147

139-
const data = await pollResponse.json()
140-
logger.info(`Bright Data Discover task ${taskId} status: ${data.status}`)
148+
const data = await pollResponse.json()
149+
logger.info(`Bright Data Discover task ${taskId} status: ${data.status}`)
150+
151+
if (data.status === 'done') {
152+
const items = Array.isArray(data.results) ? data.results : []
153+
154+
const results = items.map((item: Record<string, unknown>) => ({
155+
url: (item.link as string) ?? (item.url as string) ?? null,
156+
title: (item.title as string) ?? null,
157+
description: (item.description as string) ?? (item.snippet as string) ?? null,
158+
relevanceScore: (item.relevance_score as number) ?? null,
159+
content: (item.content as string) ?? null,
160+
}))
161+
162+
return {
163+
success: true,
164+
output: {
165+
results,
166+
query: params.query ?? null,
167+
totalResults: results.length,
168+
},
169+
}
170+
}
141171

142-
if (data.status === 'done') {
143-
const items = Array.isArray(data.results) ? data.results : []
172+
if (data.status === 'failed' || data.status === 'error') {
173+
return {
174+
...result,
175+
success: false,
176+
error: `Discover task failed: ${data.error ?? 'Unknown error'}`,
177+
}
178+
}
144179

145-
const results = items.map((item: Record<string, unknown>) => ({
146-
url: (item.link as string) ?? (item.url as string) ?? null,
147-
title: (item.title as string) ?? null,
148-
description: (item.description as string) ?? (item.snippet as string) ?? null,
149-
relevanceScore: (item.relevance_score as number) ?? null,
150-
content: (item.content as string) ?? null,
151-
}))
180+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS))
181+
elapsedTime += POLL_INTERVAL_MS
182+
} catch (error) {
183+
logger.error('Error polling for discover task:', {
184+
message: error instanceof Error ? error.message : String(error),
185+
taskId,
186+
})
152187

153188
return {
154-
success: true,
155-
output: {
156-
results,
157-
query: params.query ?? null,
158-
totalResults: results.length,
159-
},
160-
} as BrightDataDiscoverResponse
161-
}
162-
163-
if (data.status === 'failed' || data.status === 'error') {
164-
throw new Error(`Discover task failed: ${data.error ?? 'Unknown error'}`)
189+
...result,
190+
success: false,
191+
error: `Error polling for discover task: ${error instanceof Error ? error.message : String(error)}`,
192+
}
165193
}
166-
167-
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS))
168-
elapsedTime += POLL_INTERVAL_MS
169194
}
170195

171-
throw new Error(
172-
`Discover task ${taskId} timed out after ${MAX_POLL_TIME_MS / 1000}s. Check status manually.`
196+
logger.warn(
197+
`Discover task ${taskId} did not complete within the maximum polling time (${MAX_POLL_TIME_MS / 1000}s)`
173198
)
199+
200+
return {
201+
...result,
202+
success: false,
203+
error: `Discover task ${taskId} timed out after ${MAX_POLL_TIME_MS / 1000}s. Check status manually.`,
204+
}
174205
},
175206

176207
outputs: {

apps/sim/tools/brightdata/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ export interface BrightDataDiscoverResponse extends ToolResponse {
131131
}>
132132
query: string | null
133133
totalResults: number
134+
taskId?: string | null
134135
}
135136
}
136137

0 commit comments

Comments
 (0)