Skip to content

Commit 6c777e6

Browse files
committed
feat: better backend error handling
1 parent 7451a0b commit 6c777e6

5 files changed

Lines changed: 35 additions & 14 deletions

File tree

apps/backend-convex/convex/http/ai.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { cors } from 'hono/cors'
1111
import { throttle } from 'kontroll'
1212
import { z } from 'zod'
1313
import { getAgentModel } from '../../utils/agent'
14+
import { getErrorMessage, normalizePossibleSDKError } from '../../utils/error'
1415
import { buildAiSdkMessage, buildSystemPrompt } from '../../utils/message'
1516
import { api, components, internal } from '../_generated/api'
1617

@@ -191,10 +192,7 @@ aiApp
191192
model: getAgentModel({ provider, model, apiKey }),
192193
system: buildSystemPrompt({ provider, model }),
193194
messages: messagesContext,
194-
onError: (ev) => {
195-
console.error(ev.error)
196-
throw ev.error
197-
},
195+
onError: (ev) => { throw ev.error },
198196
})
199197

200198
for await (const textDelta of aiStream.textStream) {
@@ -217,16 +215,18 @@ aiApp
217215
controller.enqueue(encoder.encode(`o: ${JSON.stringify({ done: true })}\n`))
218216
controller.close()
219217
}
220-
catch (error: any) {
218+
catch (err: any) {
219+
const error = normalizePossibleSDKError(err)
220+
const errorMessage = getErrorMessage(error) ?? ''
221221
console.error(error)
222222

223-
aiResponse += `\n\nError encountered, stream stopped`
223+
aiResponse += `\n\nError encountered, stream stopped: ${error?.name ? `[${error.name}]: ` : ''}${errorMessage}`
224224

225225
doSave()
226226
await waitForSave()
227227
await c.env.runMutation(internal.messages.finishStreaming, { streamId })
228228

229-
controller.enqueue(encoder.encode(`o: ${JSON.stringify({ error: error.message })}\n`))
229+
controller.enqueue(encoder.encode(`o: ${JSON.stringify({ error: `\`\`\`\n${errorMessage}\n\`\`\`` })}\n`))
230230
controller.close()
231231
}
232232
},

apps/backend-convex/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"@openrouter/ai-sdk-provider": "^0.7.2",
2525
"ai": "^4.3.16",
2626
"convex-helpers": "^0.1.94",
27+
"destr": "^2.0.5",
2728
"hono": "^4.7.11",
2829
"zod": "^3.25.64"
2930
},

apps/backend-convex/utils/error.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { destr } from 'destr'
2+
3+
export function normalizePossibleSDKError(error: any) {
4+
if (error.name === 'AI_APICallError') {
5+
return {
6+
name: 'AI_APICallError',
7+
message: destr<any>(error.responseBody)?.error?.message ?? error.message,
8+
cause: error.cause,
9+
}
10+
}
11+
12+
return error
13+
}
14+
15+
import { ConvexError } from 'convex/values'
16+
17+
export function getErrorMessage(error: Error | null) {
18+
if (error instanceof ConvexError)
19+
return error.data.msg ?? error.data.message ?? error.data.kind ?? error.data ?? error.name
20+
21+
return error?.message ?? error
22+
}

apps/frontend/app/utils/convex.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
import { ConvexError } from 'convex/values'
1+
import { getErrorMessage } from 'backend-convex/utils/error'
22

3-
export function getConvexErrorMessage(error: Error | null) {
4-
if (error instanceof ConvexError)
5-
return error.data.msg ?? error.data.message ?? error.data.kind ?? error.data ?? error.name
6-
7-
return error?.message ?? error
8-
}
3+
export { getErrorMessage as getConvexErrorMessage }

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)