feat: normalize LLM client semantic errors#102
Merged
Conversation
ce7246a to
c692e72
Compare
52a43c3 to
7fbbb6b
Compare
7fbbb6b to
bf9fee1
Compare
bf9fee1 to
5d2f611
Compare
7d27312 to
4db5b06
Compare
vldcmp-uipath
previously approved these changes
Jul 6, 2026
Replace the typed unsupported-attachment exception with a small public error contract on UiPathError: optional error_code plus diagnostic detail. Add and export UiPathLLMErrorCode so downstream packages handle stable semantic conditions without depending on provider exception types, message text, or llm-client internals. as_uipath_error normalizes on two fixed paths: - status-bearing: walk the cause chain for an httpx.Response and map its status onto the matching UiPathAPIError subclass (status authoritative). - client-side: only when no response exists anywhere in the chain, consult the client-side classifier registry, yielding UiPathError with a stable error_code and diagnostic detail. Recognition is organized per semantic code, not per provider: a code that providers surface differently is one classifier over N matcher predicates (_UNSUPPORTED_MIME_MATCHERS), so adding a provider surfacing is one predicate and as_uipath_error never grows new branches. Bedrock Converse unsupported -MIME ValueError chains map to UiPathLLMErrorCode.UNSUPPORTED_MIME_TYPE. Bump uipath-llm-client to 1.16.2. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4db5b06 to
bcfc304
Compare
vldcmp-uipath
approved these changes
Jul 6, 2026
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
Give downstream consumers a stable, provider-independent way to handle LLM client failures — a small semantic error contract on
UiPathError— so the agent layer never parses provider exception types or message text.What changed
UiPathLLMErrorCode(currently justUNSUPPORTED_MIME_TYPE) plus optionalerror_codeand diagnosticdetailonUiPathError. Purely additive.as_uipath_errornormalizes on two fixed paths: HTTP-status-bearing errors map toUiPathAPIErrorsubclasses (status authoritative); response-less client-side rejections run the_CLIENT_SIDE_CLASSIFIERSregistry.ValueErrorchains via the_UNSUPPORTED_MIME_MATCHERSseam →UNSUPPORTED_MIME_TYPE.uipath-llm-clientto 1.16.2.Key decisions
_UNSUPPORTED_MIME_MATCHERS); adding a provider surfacing is one predicate andas_uipath_errornever grows a new branch. Rejected: a per-provider catch in the general layer, which leaks provider shape into the normalizer.httpx.Responseis mapped before any client-side classifier runs, so an incidentalValueErrorin__context__can't mislabel a genuine HTTP error.How it flows
flowchart TD E[provider or SDK exception] --> R{httpx.Response in cause chain?} R -->|yes| S[map status to UiPathAPIError subclass] R -->|no| C{client-side classifier match?} C -->|yes| K[UiPathError with stable error_code] C -->|no| G[UiPathError root]Test plan
uv run pytest tests/langchain/features/test_exception_wrapping.py tests/core/features/test_exception_wrapping.py tests/core/features/test_exceptions.py -q— 96 passeduv run ruff check .clean ·uv run pyright0 errorsKnown limitations
Two extensibility follow-ups for this pattern, deliberately out of scope until a real second surfacing lands:
error_code. Next: let the status-bearing branch attach a code on top of the status class, matched against the response body only (preserving the "real response outranks incidental chain match" guard). Markers aren't guessed before a provider actually surfaces it.uipath-langchain/chat/provider_errors.pyre-derives status codes per-provider — the coupling this contract removes. Load-bearing only for the legacyuse_new_llm_clients=Falseboto3 path that bypasseswrap_provider_errors; route it through the wrapper, then delete it.Breaking changes: none — purely additive (new enum + optional fields); existing
UiPathError/UiPathAPIErrorcatch behavior unchanged.