fix: include AI API error response body in error messages#158
Conversation
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>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughError 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 ChangesEnhanced API Error Messages
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/services/aiService.ts (2)
211-227: ⚡ Quick winConsider 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 winConsider 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
📒 Files selected for processing (2)
src/services/aiService.tssrc/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>
Summary
error.message字段Changes
src/services/aiService.ts: 在 OpenAI 和 Claude 两条请求路径中,非 OK 响应时读取 response body 并附带到错误信息src/services/backendAdapter.ts:throwTranslatedError现在会提取data.error.message或data.message等嵌套错误详情Before → After
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit