Skip to content

fix: include AI API error response body in error messages#158

Merged
AmintaCCCP merged 2 commits into
mainfrom
fix/ai-error-response-details
May 25, 2026
Merged

fix: include AI API error response body in error messages#158
AmintaCCCP merged 2 commits into
mainfrom
fix/ai-error-response-details

Conversation

@AmintaCCCP

@AmintaCCCP AmintaCCCP commented May 25, 2026

Copy link
Copy Markdown
Owner

Summary

Changes

  • src/services/aiService.ts: 在 OpenAI 和 Claude 两条请求路径中,非 OK 响应时读取 response body 并附带到错误信息
  • src/services/backendAdapter.ts: throwTranslatedError 现在会提取 data.error.messagedata.message 等嵌套错误详情

Before → After

之前: AI API error: 400 Bad Request
之后: AI API error: 400 Bad Request - {"error":{"message":"...","type":"...","code":"..."}}

之前: AI代理请求失败: 400
之后: AI代理请求失败: 400 - Invalid request: ...

Test plan

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved error messages for external API failures: responses now include additional response-body details (when available) to provide clearer context and actionable information for troubleshooting failed AI and backend requests.

Review Change Stack

When DeepSeek (or other AI providers) return 4xx/5xx errors, the
response body contains detailed error information (e.g. which parameter
is invalid, content filtering details). Previously this was discarded,
making it impossible to diagnose why specific repos fail analysis.

- aiService.ts: read response body on non-OK responses and include it
  in the thrown error for both OpenAI and Claude request paths
- backendAdapter.ts: extract nested error.message from AI proxy
  responses (DeepSeek returns { error: { message, type, code } })

Refs #153

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e2f1838f-f9a2-4c01-a61b-ef9a70fdf4c7

📥 Commits

Reviewing files that changed from the base of the PR and between b934c5e and 98f6edc.

📒 Files selected for processing (1)
  • src/services/aiService.ts

📝 Walkthrough

Walkthrough

Error handling now reads and parses non-OK HTTP response bodies and appends extracted error-details to thrown errors in AI service request paths (OpenAI/Claude/Gemini) and the backend adapter's throwTranslatedError.

Changes

Enhanced API Error Messages

Layer / File(s) Summary
AI Service error enrichment (helper + provider branches)
src/services/aiService.ts
Adds a helper to read/parse failed Response bodies and updates the OpenAI-style, Claude, and Gemini !response.ok branches to append parsed response-body detail to thrown AI API error messages.
Backend adapter error translation enrichment
src/services/backendAdapter.ts
throwTranslatedError now attempts to parse response body JSON to extract code and nested error or message, and includes the extracted detail in the thrown translated Error message.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I nibble at errors, peel back their rind,
I read the dark letters the servers left behind.
Now when APIs grumble and statuses sigh,
I fetch their full stories — no detail shall fly.
Hop, parse, and report — with clarity I bind.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: including AI API error response body in error messages. It directly matches the PR's primary objective of enriching error messages with response body details.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ai-error-response-details

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/services/aiService.ts (2)

211-227: ⚡ Quick win

Consider extracting the duplicated error detail extraction logic.

The error handling logic at lines 139-155 (OpenAI path) and lines 211-227 (Claude path) is identical. Extracting this into a private helper method would improve maintainability.

♻️ Suggested refactor

Add a helper method:

private async extractErrorDetail(response: Response): Promise<string> {
  let errorDetail = '';
  try {
    const text = await response.text();
    try {
      const errorBody = JSON.parse(text);
      errorDetail = typeof errorBody === 'object'
        ? JSON.stringify(errorBody)
        : String(errorBody);
    } catch {
      errorDetail = text;
    }
  } catch {
    // ignore
  }
  return errorDetail;
}

Then replace both blocks with:

 if (!response.ok) {
-  let errorDetail = '';
-  try {
-    const text = await response.text();
-    try {
-      const errorBody = JSON.parse(text);
-      errorDetail = typeof errorBody === 'object'
-        ? JSON.stringify(errorBody)
-        : String(errorBody);
-    } catch {
-      errorDetail = text;
-    }
-  } catch {
-    // ignore
-  }
+  const errorDetail = await this.extractErrorDetail(response);
   throw new Error(`AI API error: ${response.status} ${response.statusText}${errorDetail ? ` - ${errorDetail}` : ''}`);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/aiService.ts` around lines 211 - 227, Extract the duplicated
error-detail extraction into a private helper and call it from both
response-handling branches: add a private async method (e.g.,
extractErrorDetail(response: Response): Promise<string>) that encapsulates the
try/parse/text logic shown in the OpenAI and Claude blocks, then replace the
inline blocks around the `if (!response.ok)` checks in the OpenAI path and the
Claude path to call this helper and use its returned string when throwing the
Error; update references in aiService.ts to use the new helper from the same
class/instance scope.

280-282: ⚡ Quick win

Consider applying the same error detail extraction to the Gemini path for consistency.

The OpenAI and Claude paths now extract response body details on error (lines 139-155, 211-227), but the Gemini path still only throws status and statusText. Applying the same pattern here would provide consistent error reporting across all API types.

♻️ Proposed enhancement
 if (!response.ok) {
-  throw new Error(`AI API error: ${response.status} ${response.statusText}`);
+  const errorDetail = await this.extractErrorDetail(response);
+  throw new Error(`AI API error: ${response.status} ${response.statusText}${errorDetail ? ` - ${errorDetail}` : ''}`);
 }

Note: This assumes the helper method suggested in the earlier comment is extracted.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/aiService.ts` around lines 280 - 282, The Gemini branch
currently throws only `response.status` and `response.statusText`; change it to
extract and include the response body details (attempt response.json(), fallback
to response.text()) before throwing, matching the pattern used in the
OpenAI/Claude branches (use the same helper if available), and throw an Error
containing status, statusText and the extracted body; locate the Gemini path
where `response` is checked and the line that throws `new Error(\`AI API error:
${response.status} ${response.statusText}\`)` and replace it with the enhanced
error construction.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/services/aiService.ts`:
- Around line 211-227: Extract the duplicated error-detail extraction into a
private helper and call it from both response-handling branches: add a private
async method (e.g., extractErrorDetail(response: Response): Promise<string>)
that encapsulates the try/parse/text logic shown in the OpenAI and Claude
blocks, then replace the inline blocks around the `if (!response.ok)` checks in
the OpenAI path and the Claude path to call this helper and use its returned
string when throwing the Error; update references in aiService.ts to use the new
helper from the same class/instance scope.
- Around line 280-282: The Gemini branch currently throws only `response.status`
and `response.statusText`; change it to extract and include the response body
details (attempt response.json(), fallback to response.text()) before throwing,
matching the pattern used in the OpenAI/Claude branches (use the same helper if
available), and throw an Error containing status, statusText and the extracted
body; locate the Gemini path where `response` is checked and the line that
throws `new Error(\`AI API error: ${response.status} ${response.statusText}\`)`
and replace it with the enhanced error construction.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4e69c14e-936f-4635-8144-29f3a5fac3a9

📥 Commits

Reviewing files that changed from the base of the PR and between 4464a97 and b934c5e.

📒 Files selected for processing (2)
  • src/services/aiService.ts
  • src/services/backendAdapter.ts

Address CodeRabbit review: extract inline error body extraction into
private extractErrorDetail() helper and apply it to Gemini path too.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@AmintaCCCP AmintaCCCP merged commit cdb8947 into main May 25, 2026
5 checks passed
@AmintaCCCP AmintaCCCP deleted the fix/ai-error-response-details branch May 25, 2026 09:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant