Skip to content

Conversation

@enyst
Copy link
Collaborator

@enyst enyst commented Oct 31, 2025

Summary

Fix #979

This PR introduces a provider-agnostic error surface for the SDK and improves the context-window exceeded path when no condenser is configured.

What’s in this PR

  • New typed SDK exceptions in openhands.sdk.llm.exceptions:
    • LLMAuthenticationError
    • LLMRateLimitError
    • LLMTimeoutError
    • LLMServiceUnavailableError
    • LLMBadRequestError
    • Tweak LLMContextWindowExceedError message for clearer client guidance
  • Central exception mapping in LLM._map_exception to translate LiteLLM/OpenAI/provider exceptions to SDK-typed errors
    • Leverages existing LLM.is_context_window_exceeded_exception for robust detection across providers
  • Behavior change: if a condenser is present and a context-window issue occurs → emit CondensationRequest (unchanged); otherwise, map and rethrow as typed SDK errors (e.g., LLMContextWindowExceedError) so clients can handle consistently

Motivation
Currently, clients receive raw LiteLLM/OpenAI exceptions (BadRequestError, OpenAIError, etc.) for common cases like context window exceeded or invalid API key, which are not stable across providers. Normalizing these enables client apps (e.g., openhands-cli, integrations) to handle errors predictably.

Follow-ups suggested in issue

  • Document an “Errors” section in the SDK README with example client handlers
  • Optionally add a helper for constructing a reasonable default condenser
  • Add minimal handling in openhands-cli to catch LLMContextWindowExceedError and recommend enabling a condenser

Refs

  • Issue: SDK: Normalize context-window and auth errors; raise typed exceptions when condenser is absent

Co-authored-by: openhands [email protected]

@enyst can click here to continue refining the PR


Agent Server images for this PR

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Base Image Docs / Tags
golang golang:1.21-bookworm Link
java eclipse-temurin:17-jdk Link
python nikolaik/python-nodejs:python3.12-nodejs22 Link

Pull (multi-arch manifest)

docker pull ghcr.io/openhands/agent-server:72d8f2c-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-72d8f2c-python \
  ghcr.io/openhands/agent-server:72d8f2c-python

All tags pushed for this build

ghcr.io/openhands/agent-server:72d8f2c-golang
ghcr.io/openhands/agent-server:v1.0.0a5_golang_tag_1.21-bookworm_binary
ghcr.io/openhands/agent-server:72d8f2c-java
ghcr.io/openhands/agent-server:v1.0.0a5_eclipse-temurin_tag_17-jdk_binary
ghcr.io/openhands/agent-server:72d8f2c-python
ghcr.io/openhands/agent-server:v1.0.0a5_nikolaik_s_python-nodejs_tag_python3.12-nodejs22_binary

The 72d8f2c tag is a multi-arch manifest (amd64/arm64); your client pulls the right arch automatically.

enyst added 2 commits October 31, 2025 16:44
…auth/rate-limit/timeout/service-unavailable/bad-request\n- Map provider/litellm errors to SDK types in LLM._map_exception\n- Agent: when no condenser, rethrow mapped typed errors; still trigger condensation when available\n\nCo-authored-by: openhands <[email protected]>
@blacksmith-sh

This comment has been minimized.

@enyst enyst changed the title Normalize SDK errors for clients: typed exceptions + mapping; context-window handling without condenser Normalize SDK errors for clients Oct 31, 2025
enyst and others added 8 commits November 2, 2025 11:44
…ts\n\n- Address remaining E501 by shortening comments\n- No functional changes\n\nCo-authored-by: openhands <[email protected]>
…h mapping check

- Default message now reflects current behavior: suggest enabling a condenser or shortening inputs
- Update unit test to assert new message
- mapping.py: simplify to only call looks_like_auth_error() as it already checks exception types

Co-authored-by: openhands <[email protected]>
…vailable/InternalServer errors to LLMServiceUnavailableError

- Avoid mapping APIConnectionError to LLMServiceUnavailableError to keep backward-compatibility and satisfy retry unit test expectations

Co-authored-by: openhands <[email protected]>
@github-actions
Copy link
Contributor

github-actions bot commented Nov 2, 2025

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-sdk/openhands/sdk/agent
   agent.py1415263%111, 115–116, 123–124, 126–128, 130–132, 148, 163–165, 172–174, 176, 180, 183–184, 186, 193, 219, 224, 255, 259, 264, 275–276, 298–300, 302, 314–315, 320–321, 333–336, 345–346, 351, 363–364, 369–370, 401, 422
openhands-sdk/openhands/sdk/llm
   llm.py41816061%278, 282, 287, 291, 303, 307–309, 313–314, 325, 327, 331, 348, 373, 378, 382, 387, 398, 414, 435, 439, 454, 460–461, 480–481, 489, 514–519, 540–541, 544, 548, 560, 565–568, 575, 578, 586–591, 594, 609, 613–615, 617–618, 623–624, 626, 633, 636–641, 703–706, 711–716, 720–721, 730–732, 735–736, 773–774, 811, 825, 875, 878–880, 883–891, 895–897, 900, 903–905, 912–913, 922, 929–931, 935, 937–942, 944–961, 964–968, 970–971, 977–986, 999, 1013, 1018
openhands-sdk/openhands/sdk/llm/exceptions
   classifier.py221531%20–21, 23–24, 26–27, 40–44, 46–49
   mapping.py181327%30–31, 34–35, 37–38, 40–41, 44, 47, 50–51, 54
   types.py521865%5–6, 9, 15, 20, 27, 33, 38, 43, 54, 65, 70, 75, 80, 85, 90, 96, 101
TOTAL11141509254% 

…ry test to expect SDK typed error after max retries

- Provide consistent SDK exceptions for connectivity/service availability cases
- Keep retry mechanism unchanged; tests now validate new mapped exception type

Co-authored-by: openhands <[email protected]>
@enyst enyst marked this pull request as ready for review November 2, 2025 16:06
@OpenHands OpenHands deleted a comment from openhands-ai bot Nov 2, 2025
enyst and others added 5 commits November 2, 2025 16:49
Remove redundant test that asserted ContextWindowExceededError → LLMContextWindowExceedError mapping, which is already covered by classifier tests and typed exception message tests. Keeps mapping suite focused on auth vs generic BadRequest and passthrough behavior.

Co-authored-by: openhands <[email protected]>
…t exception cause

- Promote import to top-level per review comment
- Verify __cause__ is litellm.exceptions.APIConnectionError to ensure PR preserves provider exception chaining

Co-authored-by: openhands <[email protected]>
…r errors

- Keep condenser+context-window handling in Agent
- Otherwise re-raise since LLM.completion/responses already map to SDK-typed errors

Co-authored-by: openhands <[email protected]>
- Import is_context_window_exceeded and map_provider_exception without aliasing
- Update wrapper methods to call explicit names

Co-authored-by: openhands <[email protected]>
Copy link
Collaborator

@xingyaoww xingyaoww left a comment

Choose a reason for hiding this comment

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

LGTM! Just one comment

return reconciled

@staticmethod
def is_context_window_exceeded_exception(exception: Exception) -> bool:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we replace all occurrences of this in favor of the new API?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done! The agent actually only needs to catch the SDK exception.

enyst added 3 commits November 3, 2025 16:56
…ext_window_exceeded_exception wrapper

- Trigger condensation via except LLMContextWindowExceedError when condenser handles requests
- Simplify LLM by removing back-compat wrapper/alias

Co-authored-by: openhands <[email protected]>

# Conflicts:
#	openhands-sdk/openhands/sdk/agent/agent.py
#	openhands-sdk/openhands/sdk/llm/llm.py
Copy link
Collaborator

@xingyaoww xingyaoww left a comment

Choose a reason for hiding this comment

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

Thanks!

@xingyaoww xingyaoww merged commit be9725b into main Nov 3, 2025
14 checks passed
@xingyaoww xingyaoww deleted the sdk/error-normalization-context-auth branch November 3, 2025 19:23
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.

SDK: Normalize context-window and auth errors; raise typed exceptions when condenser is absent

4 participants