Repository navigation
fix(llm): a missing-AWS-credentials error under litellm's catch-all classes is permanent - #751
Merged
Merged
Conversation
…lasses is permanent Settles the open review threads of intel#709 (r4569209131, r4568069518): `is_run_wide(APIConnectionError("Unable to locate credentials"))` was False because `is_retryable` judged the catch-all class transient, so `model_routing` kept calling and writing failed rows. `unable to locate credentials` joins `_NON_RETRYABLE_MESSAGES` in `llm.py`, so `is_retryable` is False for it under `APIConnectionError`, `APIError` and `InternalServerError`, and `is_run_wide` is True. `routing_stop._NO_CREDENTIALS` was a copy plus that one entry and is dropped. litellm's Bedrock mapping leaves other botocore credential errors as a bare `APIConnectionError`, so the messages of `NoAuthTokenError`, `PartialCredentialsError`, `ProfileNotFound` and `UnauthorizedSSOTokenError` are added too. A retry never supplies credentials, so the retry wrappers (`LLM.ask` and the other `is_retryable` callers) now fail at the first attempt instead of after 2 + 4 + 8 s of backoff. Signed-off-by: Anton Volkov <antonwolfy@gmail.com>
|
✅ OpenCodeReview: Review complete: 0 finding(s) across 6 selected item(s). CI at Review details
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #751 +/- ##
==========================================
- Coverage 95.71% 95.71% -0.01%
==========================================
Files 414 414
Lines 55310 55309 -1
Branches 9509 9509
==========================================
- Hits 52941 52940 -1
Misses 1466 1466
Partials 903 903
🚀 New features to boost your workflow:
|
6 tasks done
vchamarthi
approved these changes
Nov 14, 2026
vchamarthi
left a comment
Contributor
There was a problem hiding this comment.
Ready to merge at dad1dc2: Adds the AWS credential texts to _NON_RETRYABLE_MESSAGES so they are permanent under litellm's catch-all classes, and makes is_run_wide read the same list. It does what it says; nothing to fix.
Verified
- Retry of aws texts: The five AWS credential texts under
APIConnectionErrorare not retried on the head and are retried on main; removingunable to locate authorization tokenfails the retry test for that text. - Routing stop:
model_routingwith a catch-all-named error carryingUnable to locate credentialsor a missing config profile makes one call and stops withpermanent_error;connection resetunder the same class is still one failed row per call. - Merge and suite: The head merges onto main with no conflict and the whole local run passes.
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
Follow-up to the review of #709, where two threads left open that a credentials error under a catch-all class is judged transient, so a routing run keeps calling and writing failed rows (review, review). No reply was posted on either; the PR merged with both open.
On
main,is_retryable(APIConnectionError("Unable to locate credentials"))is True (the class is a litellm catch-all and_NON_RETRYABLE_MESSAGESdoes not hold the text), sois_run_widereturns False at once andmodel_routingmakes every call and writes a failed row for each. The Bedrock mapping raisesAuthenticationErrorfor that exact text, so the reported #677 path was covered; the gap is any other path that wraps the text in a catch-all class. litellm's Bedrock mapping also leaves the other botocore credential errors as a bareAPIConnectionError(checked by passing each botocore exception throughlitellm.exception_typewithcustom_llm_provider="bedrock"), and those were retried three times too:is_retryableon mainNoCredentialsErrorAuthenticationError(Bedrock); the same text under a catch-all is the review caseNoAuthTokenErrorAPIConnectionErrorPartialCredentialsErrorAPIConnectionErrorProfileNotFoundAPIConnectionErrorUnauthorizedSSOTokenErrorAPIConnectionErrorChanges
dokimi/llm.py:_NON_RETRYABLE_MESSAGESgainsunable to locate credentialsand the four texts above, sois_retryableis False for them underAPIConnectionError,APIErrorandInternalServerError, andis_run_wideis True.dokimi/novelty/routing_stop.py:_NO_CREDENTIALSwas_NON_RETRYABLE_MESSAGESplus that one entry; it is dropped andis_run_widereads_NON_RETRYABLE_MESSAGESdirectly.docs/skill-novelty.md: the permanent-error paragraph names the AWS cases.tests/test_llm_retry_credentials.pyadds the five AWS texts to the credential cases (not retried: one request, no sleep);tests/test_novelty_routing_estimate_and_stop.pyadds a routing run whose provider raises the credentials error (and a missing profile) under anAPIConnectionError-named class: one call,reasonpermanent_error; and aconnection resetunder the same class is still a failed row per call.Risk
is_retryableis shared by the retry wrappers (LLM.askindokimi.llm, thenovelty/batching.pycallers and the CLI error reader), so those five texts now fail on the first attempt instead of after 2 + 4 + 8 s of backoff. A retry cannot supply credentials, a profile or a refreshed SSO session, so no retry is the right outcome. Other messages under the catch-alls, and a transientAPIConnectionError("Connection error."), are retried as before. Not added, because they can be transient:TokenRetrievalErrorandCredentialRetrievalError(a remote token or metadata endpoint failing),SSOTokenLoadError,NoRegionError(not a credential).Testing
On a Linux review host, at
dad1dc2(onmainb4bcfa4):make ci-local: 31 passed, 2 failed, 14 skipped. 20407 tests passed, 19 skipped; changed-line coverage 100% (1 line measured). The two failures are the host's:static / Install gitleaks(the download returned HTTP 504) andstatic / Scan commits(gitleaks missing, exit 127). Skipped: the matrix legs on other Pythons, semgrep, conda-forge, fuzz, deploy and the other steps that need a runner or network.APIConnectionError-named exceptions and the real litellm classes, the new tests fail atmain's code (7 failures: five credential cases, two routing cases) and pass here; the plainconnection resettest passes on both.unable to locate credentialsfrom_NON_RETRYABLE_MESSAGESfails the routing test and the retry test for that text.fix/url-extraction-delimited,test/leftovers-2026-11-14onmainb4bcfa4:pytest -n auto20429 passed, 19 skipped,mypyclean (420 source files),ruff checkclean.Revert
A plain revert restores the old behaviour. Nothing is stored.
Checklist
pytestpassesruff,mypy, and schema checks passAGENTS.md.github/.licenserc.yaml)