Skip to content

feat: normalize LLM client semantic errors#102

Merged
cotovanu-cristian merged 1 commit into
mainfrom
codex/unsupported-attachment-error
Jul 6, 2026
Merged

feat: normalize LLM client semantic errors#102
cotovanu-cristian merged 1 commit into
mainfrom
codex/unsupported-attachment-error

Conversation

@cotovanu-cristian

@cotovanu-cristian cotovanu-cristian commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

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

  • Add and export UiPathLLMErrorCode (currently just UNSUPPORTED_MIME_TYPE) plus optional error_code and diagnostic detail on UiPathError. Purely additive.
  • as_uipath_error normalizes on two fixed paths: HTTP-status-bearing errors map to UiPathAPIError subclasses (status authoritative); response-less client-side rejections run the _CLIENT_SIDE_CLASSIFIERS registry.
  • Recognize Bedrock Converse unsupported-MIME ValueError chains via the _UNSUPPORTED_MIME_MATCHERS seam → UNSUPPORTED_MIME_TYPE.
  • Bump uipath-llm-client to 1.16.2.

Key decisions

  • Recognition keyed by semantic code, not by provider. A code that providers surface differently is one classifier over N matcher predicates (_UNSUPPORTED_MIME_MATCHERS); adding a provider surfacing is one predicate and as_uipath_error never grows a new branch. Rejected: a per-provider catch in the general layer, which leaks provider shape into the normalizer.
  • HTTP status stays authoritative. A real httpx.Response is mapped before any client-side classifier runs, so an incidental ValueError in __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]
Loading

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 passed
  • uv run ruff check . clean · uv run pyright 0 errors

Known limitations

Two extensibility follow-ups for this pattern, deliberately out of scope until a real second surfacing lands:

  • Semantic code on the HTTP path. A condition arriving as an HTTP 400 (e.g. an OpenAI content rejection) gets only the status class today, not a semantic 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.
  • Downstream duplication. uipath-langchain/chat/provider_errors.py re-derives status codes per-provider — the coupling this contract removes. Load-bearing only for the legacy use_new_llm_clients=False boto3 path that bypasses wrap_provider_errors; route it through the wrapper, then delete it.

Breaking changes: none — purely additive (new enum + optional fields); existing UiPathError/UiPathAPIError catch behavior unchanged.

@cotovanu-cristian cotovanu-cristian force-pushed the codex/unsupported-attachment-error branch 2 times, most recently from ce7246a to c692e72 Compare July 1, 2026 16:41
@cotovanu-cristian cotovanu-cristian changed the title [codex] fix unsupported attachment error mapping fix: unsupported attachment error mapping Jul 6, 2026
@cotovanu-cristian cotovanu-cristian force-pushed the codex/unsupported-attachment-error branch from 52a43c3 to 7fbbb6b Compare July 6, 2026 06:30
@cotovanu-cristian cotovanu-cristian force-pushed the codex/unsupported-attachment-error branch from 7fbbb6b to bf9fee1 Compare July 6, 2026 07:27
@cotovanu-cristian cotovanu-cristian changed the title fix: unsupported attachment error mapping fix: normalize LLM client semantic errors Jul 6, 2026
@cotovanu-cristian cotovanu-cristian force-pushed the codex/unsupported-attachment-error branch from bf9fee1 to 5d2f611 Compare July 6, 2026 07:30
@cotovanu-cristian cotovanu-cristian force-pushed the codex/unsupported-attachment-error branch from 7d27312 to 4db5b06 Compare July 6, 2026 08:13
@cotovanu-cristian cotovanu-cristian changed the title fix: normalize LLM client semantic errors feat: normalize LLM client semantic errors Jul 6, 2026
vldcmp-uipath
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>
@cotovanu-cristian cotovanu-cristian merged commit f4ac413 into main Jul 6, 2026
12 checks passed
@cotovanu-cristian cotovanu-cristian deleted the codex/unsupported-attachment-error branch July 6, 2026 15:42
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