Skip to content

Detect retry-after for Anthropic errors#11719

Open
timtmok wants to merge 7 commits intomainfrom
11001-anthropic-retry-message
Open

Detect retry-after for Anthropic errors#11719
timtmok wants to merge 7 commits intomainfrom
11001-anthropic-retry-message

Conversation

@timtmok
Copy link
Contributor

@timtmok timtmok commented Feb 5, 2026

Address #11001

Returns an error indicating that the rate limit has been reached and to retry after the time specified in the response header.

The providers have been updated to check for retry-after in the response header when an error is encountered.

I'm not sure how to replicate this since I don't have a way to rate limit myself but the tests can verify the handling.

Release Notes

New Features

  • Improve error handling for exceeding rate limit for Anthropic

Bug Fixes

  • N/A

QA Notes

@timtmok timtmok requested a review from sharon-wang February 5, 2026 16:30
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

E2E Tests 🚀
This PR will run tests tagged with: @:critical

readme  valid tags

const mockConfig = {
get: (key: string, defaultValue?: any) => {
const configValues: Record<string, any> = {
'authHost': 'https://auth.test.posit.cloud',
Copy link
Member

Choose a reason for hiding this comment

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

should we use less realistic urls in this file, like auth.example.com and similar?

Comment on lines 89 to 100
suite('Rate limit error handling (Vercel SDK path)', () => {
test('throws error with retry-after when rate limited with header', () => {
const rateLimitError = createVercelRateLimitError('30', 'https://api.posit.cloud/anthropic/v1/messages');

assert.throws(
() => (model as any).handleStreamError(rateLimitError),
(error: Error) => {
assertRateLimitErrorWithRetry(error, '30');
return true;
}
);
});
Copy link
Member

Choose a reason for hiding this comment

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

I think this test and a few others in here are already covered in the other anthropic tests. What do you think about removing them from here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it's good to keep them to ensure the Posit provider is handling the retry-after in case any code in there changes. It does add several seconds to testing but it might catch something.

@@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------------------------
* Copyright (C) 2025-2026 Posit Software, PBC. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* Copyright (C) 2025-2026 Posit Software, PBC. All rights reserved.
* Copyright (C) 2026 Posit Software, PBC. All rights reserved.

@@ -0,0 +1,267 @@
/*---------------------------------------------------------------------------------------------
* Copyright (C) 2025-2026 Posit Software, PBC. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* Copyright (C) 2025-2026 Posit Software, PBC. All rights reserved.
* Copyright (C) 2026 Posit Software, PBC. All rights reserved.

@sharon-wang
Copy link
Member

sharon-wang commented Feb 5, 2026

I'm not sure how to replicate this since I don't have a way to rate limit myself but the tests can verify the handling.

Do you still have a mitm proxy tool? You could try intercepting and returning a 429 when making a request to anthropic

@timtmok
Copy link
Contributor Author

timtmok commented Feb 6, 2026

I'm not sure how to replicate this since I don't have a way to rate limit myself but the tests can verify the handling.

Do you still have a mitm proxy tool? You could try intercepting and returning a 429 when making a request to anthropic

Oh good idea!

@timtmok
Copy link
Contributor Author

timtmok commented Feb 6, 2026

It was a bit tricky to understand what was happening with Proxyman but it revealed that the Vercel provider wasn't handling the rate limit error correctly. I've added a fix for it. The Vercel SDK is set to auto-retry and the failure will wrap the rate limit error in a retry error.

image

@timtmok timtmok requested a review from sharon-wang February 6, 2026 21:44
Copy link
Member

@sharon-wang sharon-wang left a comment

Choose a reason for hiding this comment

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

a couple comments, otherwise LGTM!

*
* @param error - The error to check
* @param providerName - The name of the provider for the error message prefix
* @returns true if the error was handled (and thrown), false otherwise
Copy link
Member

Choose a reason for hiding this comment

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

should this and the vercel version of this still return boolean? the true case isn't returned for either. Maybe we can just not return anything?

Comment on lines +25 to +28
if (retryAfter) {
throw new Error(`[${providerName}] Rate limit exceeded. Please retry after ${retryAfter} seconds.`);
}
throw new Error(`[${providerName}] Rate limit exceeded. Please try again later.`);
Copy link
Member

Choose a reason for hiding this comment

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

should we add some logging here and in the vercel version below so the error is logged in output as well?

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.

2 participants