Repository navigation
fix(oauth): surface token refresh retry exhaustion as transient_error - #1225
Draft
devin-ai-integration[bot] wants to merge 1 commit into
Draft
devin-ai-integration[bot] wants to merge 1 commit into
devin-ai-integration[bot] wants to merge 1 commit into
Conversation
Co-Authored-By: bot_apk <apk@cognition.ai>
Contributor
Author
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
👋 Greetings, Airbyte Team Member!Here are some helpful tips and reminders for your convenience. 💡 Show Tips and TricksTesting This CDK VersionYou can test this version of the CDK using the following: # Run the CLI from this branch:
uvx 'git+https://github.com/airbytehq/airbyte-python-cdk.git@devin/1791877713-oauth-refresh-retry-exhaustion-transient#egg=airbyte-python-cdk[dev]' --help
# Update a connector to use the CDK from this branch ref:
cd airbyte-integrations/connectors/source-example
poe use-cdk-branch devin/1791877713-oauth-refresh-retry-exhaustion-transientPR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
|
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Resolves https://github.com/airbytehq/oncall/issues/13684:
Close on merge: yes — internally filed, no customer to confirm with.
Related to https://github.com/airbytehq/oncall/issues/13683:
When an OAuth token endpoint keeps returning 429/5xx for the whole 300s refresh backoff window, the raw
DefaultBackoffException(failure_type=transient_error)escaped the authenticator, andConcurrentReadProcessor.on_exceptionre-wrapped it assystem_errorwith the messageAn unexpected error occurred in stream <stream>: DefaultBackoffException. Provider outages (seen with source-gitlab during a GitLab.com 50X incident) were therefore routed to oncall as system errors.Fix
AbstractOauth2Authenticator(coversOauth2Authenticator,SingleUseRefreshTokenOauth2Authenticator,DeclarativeOauth2Authenticator, and the declarative single-use variant — all go through_make_handled_request):User-facing messages:
OAuth token refresh failed because the provider's token endpoint rate limited the request (HTTP 429).OAuth token refresh failed because the provider's token endpoint was temporarily unavailable (HTTP 503).No class names, URLs, or response bodies in the message. The internal message goes through
_build_provider_response_info(redacts credentials and truncates) rather thanstr(e), because withsend_refresh_request_as_query_paramsthe request URL carries the refresh token.As a backstop,
ConcurrentReadProcessor.on_exceptionnow usesBaseBackoffException.failure_type(when set) for non-ATE exceptions instead of always usingsystem_error. The templated message is unchanged, andAirbyteTracedException.from_exceptionis not touched. Only raw backoff exceptions that reach the stream thread are affected, sinceHttpClient._send_with_retryalready converts its own.Unchanged: refresh-token rejection (
config_error), network-error handling (ConnectionError/timeouts still propagate out of_make_handled_request, then get wrapped astransient_errorinrefresh_access_token), and the genericsystem_errorfallback. This does not touchhttp_client.py, so it should not conflict with #1115.Reproduction (before fix): I used a
DeclarativeOauth2Authenticatoragainst a mocked token endpoint that always returns a 503 HTML page, with time frozen andtime.sleepadvancing the clock. Backoff gave up after 11 tries (Giving up _make_handled_request(...) after 11 tries (DefaultBackoffException ...)), andon_exceptionemittedAn unexpected error occurred in stream users: DefaultBackoffException/system_error. After the fix the same script emits the 503 message above withtransient_error.Out of scope (for follow-up): In the same incident, source-gitlab's manifest maps every 401 to FAIL/
config_error("Unable to refresh theaccess_token, please re-authenticate..."), which set the job-level failure toconfig_errorwhile the token endpoint was down. That is a connector manifest change, not part of this PR.Test Coverage
New tests. Each one fails on
mainand passes with this change:test_requests_native_auth.py::TestRefreshAccessTokenRetryExhaustion:Oauth2Authenticatorwith 503/500/429, andSingleUseRefreshTokenOauth2Authenticatorwith 503. Checks for ATE +transient_error+ the exact message, no class name/URL/HTML in the message,HTTP <code>+ body ininternal_message,__cause__isDefaultBackoffException, and that the request was retried. This class is not frozen with freezegun because the class-level freeze in the neighbouring classes would blockmock_sleepfrom moving the backoff clock forward.declarative/auth/test_oauth.py: the same 503 case forDeclarativeOauth2Authenticator.test_concurrent_read_processor.py::test_on_exception_non_ate_backoff_exception_preserves_failure_type:transient_error→transient_error,config_error→config_error,None→system_error. The templated message is unchanged.Local run:
requests_native_auth/,declarative/auth/test_oauth.py,test_concurrent_read_processor.py, andtest_http_client.pyall pass (274 passed).ruff check,ruff format --check, andmypyon the changed source files are clean.Declarative-First Evaluation
Not applicable: this is a CDK runtime change, not a connector manifest change.
Link to Devin session: https://app.devin.ai/sessions/9afc93d4b13248feb7f6acc6f174e7ed
Open in Devin Desktop: https://app.devin.ai/desktop/session/9afc93d4b13248feb7f6acc6f174e7ed?variant=devin