RestateModelWrapper should not wrap `SdkInternalBaseException` as generic Exception; classify non-retryable provider errors as terminal
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
Research direction
Start at RestateModelWrapper and trace the SdkInternalBaseException handling through journaled model steps and provider failures. Compare the behavior with the linked Python error-handling and AI integration guidance. Done means internal exceptions are re-raised unchanged, non-retryable provider 4xx failures become terminal, retryable statuses follow RunOptions, and the selected policy or hook is documented.
Written by the indexing model from the issue text.
Description
When a journaled model step fails, Restate correctly uses SdkInternalException for replay control flow. The wrapper then does:
except SdkInternalBaseException as e:
raise Exception("Internal error during model call") from e
This conflicts with Restate’s Python error-handling guidance (re-raise internal exceptions; don’t catch them as generic Exception). Integrators must walk __cause__ chains to recover semantics.
For LLM provider non-retryable 4xx (e.g. invalid tool schema → HTTP 400), the failure should be TerminalError inside the journaled step, not a retryable transient. Otherwise Restate retries permanently invalid requests—contrary to the AI integration guide (“handle terminal errors”, bound LLM retries).
Proposed behavior:
except SdkInternalBaseException as e:
if isinstance(e, SuspendedException):
raise
# Optional: inspect e.__cause__ for provider HTTP errors
if is_non_retryable_provider_4xx(e.__cause__):
raise TerminalError("Model request rejected by provider", status_code=400) from e.__cause__
raise # re-raise SdkInternalBaseException unchanged — do NOT wrap in Exception(...)
Policy suggestion for upstream defaults:
| Provider status | Treatment |
|---|---|
| 400, 401, 403, 404, 422, … | TerminalError (non-retryable) |
| 408, 429 | Retryable (existing transient path) |
| 5xx | Retryable per RunOptions |
Proposals:
- Stop wrapping SdkInternalBaseException in generic Exception.
- Either adopt a default provider-status policy or expose a hook on RestateAgent / RestateModelWrapper for classifying model failures before journaling.
- Document recommended RunOptions(max_attempts=…) for LLM journal steps.
- Dominant language
- Python
- Stars
- 81
- Forks
- 22
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 2
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from restatedev/sdk-python
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
restatedev/sdk-python#223 · 1 comment ·
-
Difficulty 2/5 1-2 days Newbie friendliness 68/100
restatedev/sdk-python#204 · 1 comment ·
-
Difficulty 3/5 1-2 days Newbie friendliness 68/100
restatedev/sdk-python#222 · 1 comment ·
-
Difficulty 3/5 1-2 days Newbie friendliness 68/100
restatedev/sdk-python#221 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 38/100
restatedev/sdk-python#205 · 1 comment ·
All issues in restatedev/sdk-python
Similar issues
-
bug confirmed issue
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
open-webui/open-webui#30750 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
OpenwaterHealth/openmotion-bloodflow-app#604 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
good first issue
Difficulty 1/5 Under an hour Newbie friendliness 90/100