fix(amazon-bedrock): handled stringify exceptions

Guard diagnostic JSON serialization so circular objects and BigInt values cannot escape the provider catch block. Expanded the regression coverage to undefined, BigInt, and circular thrown values.

Fixes #5539
This commit is contained in:
roboomp
2026-07-15 00:49:22 +00:00
parent 1227727827
commit d600cce75b
3 changed files with 16 additions and 9 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
### Fixed
- Fixed Amazon Bedrock stream error handler crashing with `TypeError: undefined is not an object (evaluating 'baseMessage.includes')` when a non-`Error` value is thrown and `JSON.stringify` returns `undefined` ([#5539](https://github.com/can1357/oh-my-pi/issues/5539)).
- Fixed Amazon Bedrock stream error handling for non-`Error` values that `JSON.stringify` cannot serialize ([#5539](https://github.com/can1357/oh-my-pi/issues/5539)).
## [16.5.2] - 2026-07-14
+6 -1
View File
@@ -510,7 +510,12 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
for (const block of output.content) {
if (block.type === "toolCall") clearStreamingPartialJson(block);
}
const baseMessage = error instanceof Error ? error.message : (JSON.stringify(error) ?? String(error));
let baseMessage: string;
try {
baseMessage = error instanceof Error ? error.message : (JSON.stringify(error) ?? String(error));
} catch {
baseMessage = String(error);
}
// Enrich error with thinking block diagnostics for signature-related failures
let diagnostics = "";
if (baseMessage.includes("signature") || baseMessage.includes("thinking")) {
@@ -150,17 +150,19 @@ describe("Bedrock cross-region inference-profile geo routing", () => {
});
describe("Bedrock error handling", () => {
// Regression (#5539): a non-`Error` thrown inside the stream body where
// `JSON.stringify` returns `undefined` (e.g. `undefined`, a function, a
// circular object) must not crash the catch block via `baseMessage.includes(...)`.
// The stream must close cleanly with an error result instead of an unhandled
// `TypeError: undefined is not an object (evaluating 'baseMessage.includes')`.
test("surfaces a stream error when a non-Error value is thrown", async () => {
const circular: Record<string, unknown> = {};
circular.self = circular;
test.each([
["undefined", undefined],
["BigInt", 1n],
["circular object", circular],
])("surfaces a stream error when %s is thrown", async (_name, thrown) => {
const result = await streamBedrock(profileModel, userContext(), {
bearerToken: "test-token",
maxTokens: 16,
onPayload: () => {
throw undefined;
throw thrown;
},
}).result();