feat(protocol): Add an error type#134
Conversation
The RoutedLlmClient implementations now have a concrete error `enum` to
return. This allows the caller to identify what happened. No more
`downcast`. Particularly, it allows the caller to identify timeouts
separately from other errors.
- Before RoutedLlmClient::call returned `Result<Response, Box<dyn Error + Send + Sync>>`
- Now it returns `Result<Response, RoutedLlmClientError>`
Which has these variants (see code for messages, this is edited):
```
pub enum RoutedLlmClientError {
InvalidRequest { message: String },
Configuration { message: String },
Transport { #[source] source: BoxError},
Timeout { #[source] source: BoxError },
ContextWindowExceeded { .. },
UpstreamHttp { status: u16, body: String, },
InvalidResponse { #[source] source: BoxError },
Other(#[from] BoxError),
}
```
Signed-off-by: Graham King <grahamk@nvidia.com>
Assisted-by: Codex:GPT 5.6 Sol medium
|
@coderabbitai full review |
✅ Action performedFull review finished. |
Thanks Claude! Signed-off-by: Graham King <grahamk@nvidia.com>
WalkthroughThe PR replaces boxed routed-client errors with a typed ChangesTyped Routed Client Error Flow
Estimated code review effort: 4 (Complex) | ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/switchyard-server/src/lib.rs (1)
366-409: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick winFallback branch leaks the internal target name; use
source.to_string()for consistency.Every explicit arm here renders just the routed error's own message. The catch-all (
RoutedLlmClientError::Otherand any future unmatched variant) instead renderserror.to_string()on the outerLibsyError, whose#[error("client call to target {target:?} failed: {source}")]format embeds the internal target/model alias into the HTTP response body — inconsistent with the rest of the mapping and an avoidable bit of internal detail exposed to API callers.🔒 Suggested fix
- _ => server_error(error.to_string()), + _ => server_error(source.to_string()),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/switchyard-server/src/lib.rs` around lines 366 - 409, Update the catch-all branch in algorithm_error to return server_error(source.to_string()) instead of error.to_string(), matching the other RoutedLlmClientError arms and avoiding exposure of the outer LibsyError target name.
🧹 Nitpick comments (1)
crates/libsy-llm-client/src/client.rs (1)
217-224: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winDistinguish decode failures from body-read errors
Response::json()can fail on malformed JSON (is_decode()) or a body I/O problem (is_body()), but both currently fall through toResponseTranslation("invalid upstream JSON: ..."). Split those cases so transport failures stay inTransportand only actual JSON parse errors land inResponseTranslation.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/libsy-llm-client/src/client.rs` around lines 217 - 224, Update the `http_response.json::<Value>()` error mapping in the response-handling branch to distinguish body I/O failures from JSON decode failures: preserve timeout mapping, map `error.is_body()` failures to `LlmClientError::Transport`, and map only `error.is_decode()` failures to `LlmClientError::ResponseTranslation`. Keep the existing invalid-JSON context for decode errors and handle any remaining error variant consistently with the client’s existing error model.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/switchyard-server/src/lib.rs`:
- Around line 366-409: Update the catch-all branch in algorithm_error to return
server_error(source.to_string()) instead of error.to_string(), matching the
other RoutedLlmClientError arms and avoiding exposure of the outer LibsyError
target name.
---
Nitpick comments:
In `@crates/libsy-llm-client/src/client.rs`:
- Around line 217-224: Update the `http_response.json::<Value>()` error mapping
in the response-handling branch to distinguish body I/O failures from JSON
decode failures: preserve timeout mapping, map `error.is_body()` failures to
`LlmClientError::Transport`, and map only `error.is_decode()` failures to
`LlmClientError::ResponseTranslation`. Keep the existing invalid-JSON context
for decode errors and handle any remaining error variant consistently with the
client’s existing error model.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 20cc504e-468d-44cc-a241-56001748c9af
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock,!Cargo.lock
📒 Files selected for processing (17)
crates/libsy-llm-client/README.mdcrates/libsy-llm-client/src/client.rscrates/libsy-llm-client/src/error.rscrates/libsy/README.mdcrates/libsy/examples/ensemble.rscrates/libsy/examples/research_agent.rscrates/libsy/src/algorithms/fall_through.rscrates/libsy/src/algorithms/llm_class.rscrates/libsy/src/algorithms/rand.rscrates/libsy/src/algorithms/subagent_override.rscrates/libsy/src/core/algorithm.rscrates/libsy/src/error.rscrates/libsy/tests/observability.rscrates/protocol/Cargo.tomlcrates/protocol/src/client.rscrates/switchyard-py/src/libsy_bindings.rscrates/switchyard-server/src/lib.rs
Signed-off-by: Graham King <grahamk@nvidia.com>
Signed-off-by: Graham King <grahamk@nvidia.com>
Signed-off-by: Graham King <grahamk@nvidia.com>
The RoutedLlmClient implementations now have a concrete error
enumtoreturn. This allows the caller to identify what happened. No more
downcast. Particularly, it allows the caller to identify timeoutsseparately from other errors.
Result<Response, Box<dyn Error + Send + Sync>>Result<Response, LlmClientError>Which has these variants (see code for messages, this is edited) (note some more added in later commit):
libsy-llm-clientuses this error type directly.Signed-off-by: Graham King grahamk@nvidia.com
Assisted-by: Codex:GPT 5.6 Sol medium