This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 309ff0379 fix(web): preserve AI chat HTTP error messages (#1967)
309ff0379 is described below

commit 309ff03793aa9d092f0a1a25a956385817e54931
Author: coder999o <[email protected]>
AuthorDate: Wed Aug 19 11:49:16 2026 +0800

    fix(web): preserve AI chat HTTP error messages (#1967)
---
 web/src/api/ai.test.ts | 24 ++++++++++++++++++++++++
 web/src/api/ai.ts      | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/web/src/api/ai.test.ts b/web/src/api/ai.test.ts
index 64beff97c..9ca698287 100644
--- a/web/src/api/ai.test.ts
+++ b/web/src/api/ai.test.ts
@@ -180,6 +180,30 @@ describe('AI API', () => {
         status: 400,
       } satisfies Partial<AiStreamError>);
     });
+
+    it('throws backend error messages from failed HTTP responses', async () => 
{
+      vi.stubGlobal(
+        'fetch',
+        vi.fn().mockResolvedValue(
+          new Response(
+            JSON.stringify({
+              code: 400,
+              message: 'Chat request is required',
+              data: null,
+            }),
+            { status: 400, statusText: 'Bad Request' },
+          ),
+        ),
+      );
+
+      await expect(
+        chatStream({ message: '', mode: 'chat', model: 'stub' }, vi.fn()),
+      ).rejects.toMatchObject({
+        name: 'AiStreamError',
+        message: 'Chat request is required',
+        status: 400,
+      } satisfies Partial<AiStreamError>);
+    });
   });
 
   describe('executeAiCommand', () => {
diff --git a/web/src/api/ai.ts b/web/src/api/ai.ts
index 3a203e43a..8044adc53 100644
--- a/web/src/api/ai.ts
+++ b/web/src/api/ai.ts
@@ -110,6 +110,33 @@ function parseStreamError(payload: string): AiStreamError {
   }
 }
 
+async function parseHttpError(response: Response): Promise<AiStreamError> {
+  const fallback = response.statusText || `HTTP ${response.status}`;
+  try {
+    const payload = await response.text();
+    if (!payload.trim()) {
+      return new AiStreamError(
+        `AI chat failed: ${fallback}`,
+        undefined,
+        undefined,
+        response.status,
+      );
+    }
+    try {
+      const parsed = JSON.parse(payload) as AiStreamPayload;
+      const message = typeof parsed.message === 'string' ? parsed.message : 
payload;
+      const code = typeof parsed.code === 'string' ? parsed.code : undefined;
+      const hint = typeof parsed.hint === 'string' ? parsed.hint : undefined;
+      const status = typeof parsed.status === 'number' ? parsed.status : 
response.status;
+      return new AiStreamError(message, code, hint, status);
+    } catch {
+      return new AiStreamError(payload, undefined, undefined, response.status);
+    }
+  } catch {
+    return new AiStreamError(`AI chat failed: ${fallback}`, undefined, 
undefined, response.status);
+  }
+}
+
 function emitEvent(
   event: string,
   onChunk: (text: string) => void,
@@ -170,7 +197,10 @@ export async function chatStream(
     signal,
   });
 
-  if (!response.ok || !response.body) {
+  if (!response.ok) {
+    throw await parseHttpError(response);
+  }
+  if (!response.body) {
     throw new Error(`AI chat failed: ${response.statusText}`);
   }
 

Reply via email to