fix(worker): resolve 'Body has already been used' error on retry#5573
fix(worker): resolve 'Body has already been used' error on retry#5573colegottdank wants to merge 5 commits intomainfrom
Conversation
Previously, reasoning_effort "medium" was incorrectly mapped to thinkingLevel "low" for all Gemini 3 models. This caused inconsistent thinking behavior compared to using Vertex directly. Google's API supports "low", "medium", "high" for thinkingLevel (Flash also supports "minimal"), which matches OpenAI's reasoning_effort values. Now we pass through the value directly instead of mapping. - Remove unnecessary mapping function - Pass reasoning_effort directly as thinkingLevel for Gemini 3+ models - Add "medium" to GeminiThinkingConfig type - Update tests to reflect pass-through behavior Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The documentation interface was missing the "medium" thinking level option that is supported by Gemini 3 Flash models. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The "minimal" thinking level is supported by Gemini Flash models but was missing from GeminiThinkingConfig and GoogleThinkingConfig. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added best practices for modifying TypeScript types: - Run tsc --noEmit before committing - Search for related types when updating union types - Check cross-package dependencies - Run full build to catch type errors Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When callProviderWithRetry() retried requests after 429 or 5xx responses, it would fail with "Body has already been used" errors. This occurred because ReadableStream bodies can only be consumed once by fetch(). The fix converts any ReadableStream body to a string before entering the retry loop, allowing the body to be safely reused across retry attempts. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Claude finished @colegottdank's task —— View job Code Review CompleteScore: 8/10 - Good to merge, minor suggestions for improvement This PR successfully fixes the "Body has already been used" error in the worker's retry logic. The core fix is solid and the approach is correct. Core Fix Analysis (ProviderClient.ts)✅ Problem identification: Correctly identified that ✅ Solution approach: Converting ReadableStream to string before retry loop is the right approach ✅ Implementation: Clean implementation with proper error handling Minor suggestions for the core fix:
Google Provider Changes AnalysisThe Google provider changes appear to be related to adding support for reasoning/thinking features: ✅ Type additions: Added ✅ Test coverage: Comprehensive test coverage for the reasoning functionality in ✅ Documentation: Good inline comments explaining the reasoning configuration logic Observations on Google changes:
Potential Issues FoundMinor Performance Issue: In // Current approach
retryableBody = chunks.map((chunk) => decoder.decode(chunk)).join("");
// More efficient approach would be:
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
const combined = new Uint8Array(totalLength);
let offset = 0;
for (const chunk of chunks) {
combined.set(chunk, offset);
offset += chunk.length;
}
retryableBody = decoder.decode(combined);Type Safety Enhancement: Consider adding runtime validation for the body conversion to ensure the conversion doesn't fail silently. Security & Quality Assessment✅ No security issues identified Suggestions Summary:Critical fixes needed: None Recommended improvements:
Optional enhancements:
The fix addresses the core issue effectively and the Google provider enhancements are well-implemented. The code quality is good and follows project conventions. |
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
Summary
ReadableStreambody to string before the retry loop so it can be safely reusedProblem
When
callProviderWithRetry()retried requests after receiving 429 or 5xx responses from providers, the retry would fail with "Body has already been used" errors. This happened because:bodyincallPropscould be aReadableStream(whenRequestBodyBuffer_Remoteis used for large requests)ReadableStreambodies can only be consumed once byfetch()Solution
Convert any
ReadableStreambody to a string at the start ofcallProviderWithRetry()before entering the retry loop. Strings can be safely reused across multiplefetch()calls.Test plan
🤖 Generated with Claude Code