Skip to content

Commit 2e6ac62

Browse files
committed
fix: enhance Bedrock error messages in retry system
- Throw enhanced error messages instead of original errors in createMessage() and completePrompt() - Users now see detailed error codes, request IDs, and troubleshooting guidance during retry countdowns - Add comprehensive tests to verify enhanced error messages flow to retry system - Resolves issue #4745 where retry messages only showed basic errors instead of verbose details
1 parent 82a9025 commit 2e6ac62

File tree

2 files changed

+96
-3
lines changed

2 files changed

+96
-3
lines changed

src/api/providers/__tests__/bedrock-error-handling.spec.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,4 +389,74 @@ describe("AwsBedrockHandler Error Handling", () => {
389389
}
390390
})
391391
})
392+
393+
describe("Enhanced Error Throw for Retry System", () => {
394+
it("should throw enhanced error messages for completePrompt to display in retry system", async () => {
395+
const throttlingError = createMockError({
396+
message: "Too many tokens, rate limited",
397+
status: 429,
398+
$metadata: {
399+
httpStatusCode: 429,
400+
requestId: "test-request-id-12345",
401+
},
402+
})
403+
mockSend.mockRejectedValueOnce(throttlingError)
404+
405+
try {
406+
await handler.completePrompt("test")
407+
throw new Error("Expected error to be thrown")
408+
} catch (error) {
409+
// Should contain error codes (note: completePrompt adds "Bedrock completion error: " prefix)
410+
expect(error.message).toContain("[HTTP 429")
411+
// Should contain the verbose message template
412+
expect(error.message).toContain("Request was throttled or rate limited")
413+
// Should contain debug information
414+
expect(error.message).toContain("Request ID: test-request-id-12345")
415+
// Should preserve original error properties
416+
expect((error as any).status).toBe(429)
417+
expect((error as any).$metadata.requestId).toBe("test-request-id-12345")
418+
}
419+
})
420+
421+
it("should throw enhanced error messages for createMessage streaming to display in retry system", async () => {
422+
const tokenError = createMockError({
423+
message: "Too many tokens in request",
424+
name: "ValidationException",
425+
$metadata: {
426+
httpStatusCode: 400,
427+
requestId: "token-error-id-67890",
428+
extendedRequestId: "extended-12345",
429+
},
430+
})
431+
432+
const mockStream = {
433+
[Symbol.asyncIterator]() {
434+
return {
435+
async next() {
436+
throw tokenError
437+
},
438+
}
439+
},
440+
}
441+
442+
mockSend.mockResolvedValueOnce({ stream: mockStream })
443+
444+
try {
445+
const stream = handler.createMessage("system", [{ role: "user", content: "test" }])
446+
for await (const chunk of stream) {
447+
// Should not reach here as it should throw an error
448+
}
449+
throw new Error("Expected error to be thrown")
450+
} catch (error) {
451+
// Should contain error codes (note: this will be caught by the non-throttling error path)
452+
expect(error.message).toContain("Too many tokens")
453+
// Should contain debug information
454+
expect(error.message).toContain("Request ID: token-error-id-67890")
455+
expect(error.message).toContain("Extended Request ID: extended-12345")
456+
// Should preserve original error properties
457+
expect(error.name).toBe("ValidationException")
458+
expect((error as any).$metadata.requestId).toBe("token-error-id-67890")
459+
}
460+
})
461+
})
392462
})

src/api/providers/bedrock.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -581,9 +581,19 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
581581
yield chunk as any // Cast to any to bypass type checking since we know the structure is correct
582582
}
583583

584-
// Re-throw the error
584+
// Re-throw with enhanced error message so retry system shows verbose details
585+
const enhancedErrorMessage = this.formatErrorMessage(error, this.getErrorType(error), true)
585586
if (error instanceof Error) {
586-
throw error
587+
const enhancedError = new Error(enhancedErrorMessage)
588+
// Preserve important properties from the original error
589+
enhancedError.name = error.name
590+
if ((error as any).status) {
591+
;(enhancedError as any).status = (error as any).status
592+
}
593+
if ((error as any).$metadata) {
594+
;(enhancedError as any).$metadata = (error as any).$metadata
595+
}
596+
throw enhancedError
587597
} else {
588598
throw new Error("An unknown error occurred")
589599
}
@@ -651,7 +661,20 @@ export class AwsBedrockHandler extends BaseProvider implements SingleCompletionH
651661
const errorResult = this.handleBedrockError(error, false) // false for non-streaming context
652662
// Since we're in a non-streaming context, we know the result is a string
653663
const errorMessage = errorResult as string
654-
throw new Error(errorMessage)
664+
665+
// Create enhanced error with verbose details for retry system
666+
const enhancedError = new Error(errorMessage)
667+
if (error instanceof Error) {
668+
// Preserve important properties from the original error
669+
enhancedError.name = error.name
670+
if ((error as any).status) {
671+
;(enhancedError as any).status = (error as any).status
672+
}
673+
if ((error as any).$metadata) {
674+
;(enhancedError as any).$metadata = (error as any).$metadata
675+
}
676+
}
677+
throw enhancedError
655678
}
656679
}
657680

0 commit comments

Comments
 (0)