refactor(inference): rename RouteError to Error (#47771)

Every other crate names its error Error. The format crates already re-exported
it under that name, so only the inference crate and a few importers change
This commit is contained in:
yujonglee 2026-10-21 07:03:18 -07:00 • committed by GitHub
parent 3f93350411
commit b6f91a221b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 104 additions and 104 deletions

View file

@ -72,26 +72,26 @@ fn duration(seconds: f64) -> Result<Duration, Error> {
#[derive(Clone, Default)]
pub(crate) struct CacheHeaders(std::sync::Arc<std::sync::OnceLock<String>>);
impl litellm_host::interceptors::Interceptors<litellm_inference::RouteError> for CacheHeaders {
impl litellm_host::interceptors::Interceptors<litellm_inference::Error> for CacheHeaders {
async fn before_provider_request(
&self,
wire: litellm_host::interceptors::WireRequest,
_: litellm_host::interceptors::RequestContext,
) -> Result<litellm_host::interceptors::WireRequest, litellm_inference::RouteError> {
) -> Result<litellm_host::interceptors::WireRequest, litellm_inference::Error> {
Ok(wire)
}
async fn after_provider_response(
&self,
_: litellm_host::interceptors::RawResponse,
) -> Result<(), litellm_inference::RouteError> {
) -> Result<(), litellm_inference::Error> {
Ok(())
}
async fn result_ready(
&self,
facts: litellm_host::interceptors::ExecutionFacts,
) -> Result<(), litellm_inference::RouteError> {
) -> Result<(), litellm_inference::Error> {
if let litellm_host::interceptors::ResultSource::Cache { key } = facts.source {
let _ = self.0.set(key);
}

View file

@ -4,7 +4,7 @@ use axum::{
response::{IntoResponse, Response},
};
use litellm_http::transport::Error as TransportError;
use litellm_inference::RouteError;
use litellm_inference::Error as InferenceError;
use litellm_llms::base_llm::ocr::error::Error as OcrError;
use serde_json::{Map, Value, json};
@ -19,7 +19,7 @@ pub enum Error {
)]
UnknownModel(String),
#[error(transparent)]
Route(#[from] RouteError),
Route(#[from] InferenceError),
#[error(transparent)]
Ocr(#[from] OcrError),
#[error("{0} is not implemented by the Rust gateway")]
@ -36,8 +36,8 @@ impl IntoResponse for Error {
}
}
impl From<litellm_host_http::Error<RouteError>> for Error {
fn from(error: litellm_host_http::Error<RouteError>) -> Self {
impl From<litellm_host_http::Error<InferenceError>> for Error {
fn from(error: litellm_host_http::Error<InferenceError>) -> Self {
match error {
litellm_host_http::Error::Call(error) => Self::Route(error),
litellm_host_http::Error::Protocol => Self::Internal(error.to_string()),
@ -50,7 +50,7 @@ impl Error {
match self {
Self::Auth(error) => error.status(),
Self::Unsupported(_)
| Self::Route(RouteError::Unsupported(_))
| Self::Route(InferenceError::Unsupported(_))
| Self::Ocr(OcrError::Unsupported(_)) => StatusCode::NOT_IMPLEMENTED,
Self::BodyTooLarge => StatusCode::PAYLOAD_TOO_LARGE,
Self::Ocr(
@ -64,10 +64,10 @@ impl Error {
.and_then(|status| StatusCode::from_u16(status).ok())
.unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
Self::InvalidBody(_) | Self::UnknownModel(_) => StatusCode::BAD_REQUEST,
Self::Route(RouteError::Transport(TransportError::Http { status, .. })) => {
Self::Route(InferenceError::Transport(TransportError::Http { status, .. })) => {
StatusCode::from_u16(*status).unwrap_or(StatusCode::BAD_GATEWAY)
}
Self::Route(RouteError::Auth(litellm_auth::Error::MissingApiKey { .. })) => {
Self::Route(InferenceError::Auth(litellm_auth::Error::MissingApiKey { .. })) => {
StatusCode::UNAUTHORIZED
}
Self::Route(error) if error.is_request() => StatusCode::BAD_REQUEST,
@ -97,7 +97,9 @@ impl Error {
/// body already in that shape passes through, any other has its message extracted.
pub fn body(&self, request_id: Option<&str>) -> Value {
let raw = match self {
Self::Route(RouteError::Transport(TransportError::Http { body, .. })) => body.clone(),
Self::Route(InferenceError::Transport(TransportError::Http { body, .. })) => {
body.clone()
}
other => other.to_string(),
};
let parsed = serde_json::from_str::<Value>(&raw).ok();
@ -175,7 +177,7 @@ mod tests {
use super::*;
fn upstream(status: u16, body: &str) -> Error {
Error::Route(RouteError::Transport(TransportError::Http {
Error::Route(InferenceError::Transport(TransportError::Http {
status,
body: body.into(),
}))
@ -225,16 +227,16 @@ mod tests {
#[rstest]
#[case::upstream_status(upstream(429, ""), StatusCode::TOO_MANY_REQUESTS)]
#[case::rejected_request(Error::Route(RouteError::InvalidRequest("top_k".into())), StatusCode::BAD_REQUEST)]
#[case::rejected_request(Error::Route(InferenceError::InvalidRequest("top_k".into())), StatusCode::BAD_REQUEST)]
#[case::missing_key(
Error::Route(RouteError::Auth(litellm_auth::Error::MissingApiKey {
Error::Route(InferenceError::Auth(litellm_auth::Error::MissingApiKey {
provider: "Anthropic",
environment_variable: "ANTHROPIC_API_KEY",
})),
StatusCode::UNAUTHORIZED,
)]
#[case::lost_connection(
Error::Route(RouteError::Transport(TransportError::Network("reset".into()))),
Error::Route(InferenceError::Transport(TransportError::Network("reset".into()))),
StatusCode::INTERNAL_SERVER_ERROR,
)]
fn status_follows_who_is_at_fault(#[case] error: Error, #[case] status: StatusCode) {

View file

@ -1,7 +1,7 @@
use litellm_host::observation::ObservationSender;
pub mod route;
pub mod types;
pub use litellm_inference::RouteError as Error;
pub use litellm_inference::Error;
mod common_utils;
pub mod constants;
pub(crate) mod handler;

View file

@ -21,7 +21,7 @@ use litellm_host::{
lifecycle::{CallEvent, ExecutionEvent},
observation::observation_channel,
};
use litellm_inference::RouteError;
use litellm_inference::Error;
use rstest::{fixture, rstest};
use serde_json::{Value, json};
@ -166,12 +166,12 @@ struct ChangingHooks {
facts: std::sync::Mutex<Vec<ExecutionFacts>>,
}
impl Interceptors<RouteError> for ChangingHooks {
impl Interceptors<Error> for ChangingHooks {
async fn before_provider_request(
&self,
mut wire: WireRequest,
_: RequestContext,
) -> Result<WireRequest, RouteError> {
) -> Result<WireRequest, Error> {
let call = self.calls.fetch_add(1, Ordering::SeqCst);
if self.rewrite {
wire.body["temperature"] = json!(if call < 2 { 0.1 } else { 0.8 });
@ -179,11 +179,11 @@ impl Interceptors<RouteError> for ChangingHooks {
Ok(wire)
}
async fn after_provider_response(&self, _: RawResponse) -> Result<(), RouteError> {
async fn after_provider_response(&self, _: RawResponse) -> Result<(), Error> {
Ok(())
}
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
self.facts.lock().unwrap().push(facts);
Ok(())
}

View file

@ -14,7 +14,7 @@ use std::sync::Arc;
use crate::common_utils::messages_provider;
pub use litellm_inference::RouteError as Error;
pub use litellm_inference::Error;
pub use types::{
MessagesCall, MessagesCallResponse, MessagesSettings, MessagesShaping, litellm_params,
messages_body,

View file

@ -17,7 +17,7 @@ use litellm_host::interceptors::{
ResultSource, WireRequest,
};
use litellm_inference::{
RouteError,
Error,
caching::{CacheRequest, execute_unary},
};
use rstest::{fixture, rstest};
@ -133,12 +133,12 @@ struct ChangingHooks {
facts: std::sync::Mutex<Vec<ExecutionFacts>>,
}
impl Interceptors<RouteError> for ChangingHooks {
impl Interceptors<Error> for ChangingHooks {
async fn before_provider_request(
&self,
mut wire: WireRequest,
_: RequestContext,
) -> Result<WireRequest, RouteError> {
) -> Result<WireRequest, Error> {
let call = self.calls.fetch_add(1, Ordering::SeqCst);
if self.rewrite {
wire.body["temperature"] = json!(if call < 2 { 0.1 } else { 0.8 });
@ -146,11 +146,11 @@ impl Interceptors<RouteError> for ChangingHooks {
Ok(wire)
}
async fn after_provider_response(&self, _: RawResponse) -> Result<(), RouteError> {
async fn after_provider_response(&self, _: RawResponse) -> Result<(), Error> {
Ok(())
}
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
self.facts.lock().unwrap().push(facts);
Ok(())
}

View file

@ -3,4 +3,4 @@
- The route returns its completed response directly
- Route closures supply OCR-specific host capabilities, such as the caller's Azure AD token provider (`src/route.rs`)
- Provider code reaches the caller's hooks mid-call only through `litellm_llms::base_llm::ocr::handler::CallHooks`, which this crate implements over its host until it folds into `litellm_host::interceptors::Interceptors`
- OCR failures use `base_llm/ocr/error.rs`, the recorded exception to `litellm_inference::RouteError` until OCR folds into `litellm_llms::Error`
- OCR failures use `base_llm/ocr/error.rs`, the recorded exception to `litellm_inference::Error` until OCR folds into `litellm_llms::Error`

View file

@ -249,7 +249,7 @@ pub(crate) fn resolve_provider_config<'a>(
provider: LlmProviders::Mistral,
}
}
Err(litellm_inference::RouteError::InvalidProvider(provider)) => {
Err(litellm_inference::Error::InvalidProvider(provider)) => {
return Err(Error::InvalidProvider(provider));
}
Err(error) => return Err(Error::InvalidProvider(error.to_string())),

View file

@ -1,5 +1,5 @@
use litellm_host::observation::ObservationSender;
pub use litellm_inference::RouteError as Error;
pub use litellm_inference::Error;
pub mod ids;
pub mod route;

View file

@ -18,7 +18,7 @@ use litellm_host::interceptors::{
WireRequest,
};
use litellm_inference::{
RouteError,
Error,
caching::{CacheRequest, execute_unary},
};
use rstest::{fixture, rstest};
@ -124,12 +124,12 @@ struct ChangingHooks {
facts: std::sync::Mutex<Vec<ExecutionFacts>>,
}
impl Interceptors<RouteError> for ChangingHooks {
impl Interceptors<Error> for ChangingHooks {
async fn before_provider_request(
&self,
mut wire: WireRequest,
_: RequestContext,
) -> Result<WireRequest, RouteError> {
) -> Result<WireRequest, Error> {
let call = self.calls.fetch_add(1, Ordering::SeqCst);
if self.rewrite {
wire.body["temperature"] = json!(if call < 2 { 0.1 } else { 0.8 });
@ -137,11 +137,11 @@ impl Interceptors<RouteError> for ChangingHooks {
Ok(wire)
}
async fn after_provider_response(&self, _: RawResponse) -> Result<(), RouteError> {
async fn after_provider_response(&self, _: RawResponse) -> Result<(), Error> {
Ok(())
}
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
self.facts.lock().unwrap().push(facts);
Ok(())
}

View file

@ -1,5 +1,5 @@
pub mod types;
pub use litellm_inference::RouteError as Error;
pub use litellm_inference::Error;
mod constants;
mod handler;

View file

@ -2,7 +2,7 @@
- `gateway-inference` (serving) -> `inference-<fmt>` (one API's call) -> `inference` (shared base)
- This crate is the shared base every format crate builds on
- `RouteError` (`src/error.rs`), `CallOptions` (`src/lib.rs`), `CallContext` (`src/context.rs`)
- `Error` (`src/error.rs`), `CallOptions` (`src/lib.rs`), `CallContext` (`src/context.rs`)
- diagnostic spans (`src/diagnostic.rs`), outbound send and signing (`src/outbound.rs`), provider resolution (`src/provider.rs`), `CoreResources` (`src/resources.rs`)
- response caching (`src/caching.rs`): `Cachable`, `StreamCachable`, `CacheRequest`, `CallCache`, `execute_unary`, `execute_streaming`, stream capture
- Shared test helpers belong in litellm-inference-testing, used only as a dev dependency
@ -49,14 +49,14 @@
- `litellm-inference-<fmt>` mirrors the route packages (`litellm/ocr/`, `litellm/messages/`, ...)
- Provider code never imports from `inference` or `inference-*`
- Handlers belong in `inference-*` or `llms`, never in a host crate
- Import every item from its canonical path. Never re-export another crate's items or give an item a second public path. The only allowed re-exports are a private submodule surfacing its item at its module root (`mod error; pub use error::Error;`) and each format crate's `pub use litellm_inference::RouteError as Error;`, which keeps the pre-split `<fmt>::Error` name
- Import every item from its canonical path. Never re-export another crate's items or give an item a second public path. The only allowed re-exports are a private submodule surfacing its item at its module root (`mod error; pub use error::Error;`) and each format crate's `pub use litellm_inference::Error;`, which keeps the pre-split `<fmt>::Error` name
## Error placement
- The workspace `Error definitions` rules shape each crate's error. This section decides which crate and module a failure belongs to
- A failure is declared once, by the lowest crate that raises it
- every crate above nests it unchanged (`#[error(transparent)] Auth(#[from] litellm_auth::Error)`) or maps it once at its boundary, as `src/error.rs` does for `litellm_llms::Error`
- `RouteError` collects route failures for every format crate and never re-declares a variant a lower crate raises
- `Error` collects route failures for every format crate and never re-declares a variant a lower crate raises
- Scope follows the concept, not the first caller
- an error type under `litellm-llms`'s `<provider>/` is private to that provider: no other provider and nothing in `base_llm` may import it
- a failure two providers or two routes can hit (wire framing, stream event decoding, a malformed provider response) belongs to the crate that owns the concept: `litellm-framer` for framing, `litellm_llms::Error` for the transformation layer

View file

@ -24,9 +24,9 @@ use serde::{Deserialize, Serialize, de::DeserializeOwned};
use serde_json::Value;
use tokio_util::codec::Decoder;
use crate::RouteError;
use crate::Error;
pub trait Cachable: Protocol<Error = RouteError> {
pub trait Cachable: Protocol<Error = Error> {
const SURFACE: &'static str;
fn reusable(_response: &Self::Response) -> bool {
@ -145,15 +145,15 @@ pub async fn execute_unary<P, F, Fut>(
request: CacheRequest,
cache: Option<Arc<dyn ResponseCacheService>>,
options: Option<CacheOptions>,
interceptors: &impl Interceptors<RouteError>,
interceptors: &impl Interceptors<Error>,
observers: Option<&ObservationSender>,
provider: F,
) -> Result<P::Response, RouteError>
) -> Result<P::Response, Error>
where
P: Cachable,
P::Response: Serialize + DeserializeOwned,
F: FnOnce() -> Fut,
Fut: Future<Output = Result<P::Response, RouteError>>,
Fut: Future<Output = Result<P::Response, Error>>,
{
let identity = request.identity.clone();
crate::diagnostic::provider(&identity.model, &identity.provider);
@ -191,15 +191,15 @@ pub async fn execute_streaming<P, F, Fut>(
request: CacheRequest,
cache: Option<Arc<dyn ResponseCacheService>>,
options: Option<CacheOptions>,
interceptors: &impl Interceptors<RouteError>,
interceptors: &impl Interceptors<Error>,
observers: Option<&ObservationSender>,
provider: F,
) -> Result<OutputOf<P>, RouteError>
) -> Result<OutputOf<P>, Error>
where
P: StreamCachable,
P::Response: Serialize + DeserializeOwned,
F: FnOnce() -> Fut,
Fut: Future<Output = Result<OutputOf<P>, RouteError>>,
Fut: Future<Output = Result<OutputOf<P>, Error>>,
{
let identity = request.identity.clone();
crate::diagnostic::provider(&identity.model, &identity.provider);
@ -299,9 +299,9 @@ impl<P: StreamCachable> CallCache<P> {
}
fn capture_stream<P: StreamCachable>(
chunks: futures_util::stream::BoxStream<'static, Result<P::Chunk, RouteError>>,
chunks: futures_util::stream::BoxStream<'static, Result<P::Chunk, Error>>,
session: CacheSession,
) -> futures_util::stream::BoxStream<'static, Result<P::Chunk, RouteError>> {
) -> futures_util::stream::BoxStream<'static, Result<P::Chunk, Error>> {
stream::try_unfold(
(chunks, Some(Vec::<u8>::new()), session),
|(mut chunks, captured, session)| async move {
@ -330,7 +330,7 @@ fn capture_stream<P: StreamCachable>(
{
session.store(entry).await;
}
Ok::<_, RouteError>(None)
Ok::<_, Error>(None)
}
}
},
@ -369,9 +369,9 @@ fn successful_stream(text: &str, terminal: &str) -> bool {
async fn publish(
facts: ExecutionFacts,
interceptors: &impl Interceptors<RouteError>,
interceptors: &impl Interceptors<Error>,
observers: Option<&ObservationSender>,
) -> Result<(), RouteError> {
) -> Result<(), Error> {
if let Some(observers) = observers {
observers.emit(CallEvent::Execution(ExecutionEvent::ResultReady {
facts: facts.clone(),

View file

@ -5,7 +5,7 @@ use litellm_host::{
observation::ObservationSender,
};
use crate::{CallOptions, RouteError};
use crate::{CallOptions, Error};
pub struct CallContext<'a, I> {
pub interceptors: &'a I,
@ -13,7 +13,7 @@ pub struct CallContext<'a, I> {
pub cache: CachePolicy,
}
impl<'a, I: Interceptors<RouteError>> CallContext<'a, I> {
impl<'a, I: Interceptors<Error>> CallContext<'a, I> {
pub fn new(interceptors: &'a I, options: CallOptions) -> Self {
Self {
interceptors,
@ -22,7 +22,7 @@ impl<'a, I: Interceptors<RouteError>> CallContext<'a, I> {
}
}
pub async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
pub async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
if let Some(observers) = &self.observers {
observers.emit(CallEvent::Execution(ExecutionEvent::ResultReady {
facts: facts.clone(),
@ -31,7 +31,7 @@ impl<'a, I: Interceptors<RouteError>> CallContext<'a, I> {
self.interceptors.result_ready(facts).await
}
pub async fn response_received(&self, body: &str) -> Result<(), RouteError> {
pub async fn response_received(&self, body: &str) -> Result<(), Error> {
let raw = RawResponse {
body: body.to_owned(),
};
@ -43,6 +43,6 @@ impl<'a, I: Interceptors<RouteError>> CallContext<'a, I> {
self.interceptors
.after_provider_response(raw)
.await
.map_err(RouteError::post_call)
.map_err(Error::post_call)
}
}

View file

@ -11,7 +11,7 @@ use litellm_http::transport::Error as TransportError;
use litellm_llms::Error as LlmError;
#[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
pub enum RouteError {
pub enum Error {
#[error("expected {expected}, got {actual}")]
InvalidType {
expected: &'static str,
@ -38,10 +38,10 @@ pub enum RouteError {
#[error(transparent)]
Secret(#[from] SecretError),
#[error("post-call hook failed: {0}")]
PostCallHook(#[source] Arc<RouteError>),
PostCallHook(#[source] Arc<Error>),
}
impl From<litellm_host::machine::MachineFault> for RouteError {
impl From<litellm_host::machine::MachineFault> for Error {
fn from(fault: litellm_host::machine::MachineFault) -> Self {
use litellm_host::machine::MachineFault;
Self::InvalidRequest(match fault {
@ -51,7 +51,7 @@ impl From<litellm_host::machine::MachineFault> for RouteError {
}
}
impl RouteError {
impl Error {
pub fn post_call(error: Self) -> Self {
Self::PostCallHook(Arc::new(error))
}
@ -76,7 +76,7 @@ impl RouteError {
}
}
impl From<LlmError> for RouteError {
impl From<LlmError> for Error {
fn from(error: LlmError) -> Self {
match error {
LlmError::InvalidType { expected, actual } => Self::InvalidType { expected, actual },
@ -99,7 +99,7 @@ impl SecretError {
}
}
impl From<litellm_secrets::Error> for RouteError {
impl From<litellm_secrets::Error> for Error {
fn from(error: litellm_secrets::Error) -> Self {
Self::Secret(SecretError(Arc::new(error)))
}
@ -115,22 +115,22 @@ impl Eq for SecretError {}
#[cfg(test)]
mod tests {
use super::RouteError;
use super::Error;
use litellm_llms::{Error as LlmError, ErrorDetail};
use rstest::rstest;
#[test]
fn a_missing_api_key_is_the_environment_not_the_request() {
assert!(
!RouteError::Auth(litellm_auth::Error::MissingApiKey {
!Error::Auth(litellm_auth::Error::MissingApiKey {
provider: "Anthropic",
environment_variable: "ANTHROPIC_API_KEY",
})
.is_request()
);
assert!(RouteError::Auth(litellm_auth::Error::InvalidHeader).is_request());
assert!(RouteError::InvalidRequest("top_k".into()).is_request());
assert!(!RouteError::InvalidResponse("bad json".into()).is_request());
assert!(Error::Auth(litellm_auth::Error::InvalidHeader).is_request());
assert!(Error::InvalidRequest("top_k".into()).is_request());
assert!(!Error::InvalidResponse("bad json".into()).is_request());
}
#[rstest]
#[case::request(true)]
@ -139,7 +139,7 @@ mod tests {
let source = serde_json::from_str::<serde_json::Value>("{").unwrap_err();
let source_message = source.to_string();
let detail = ErrorDetail::invalid("test payload", source);
let error = RouteError::from(if request {
let error = Error::from(if request {
LlmError::InvalidRequest(detail)
} else {
LlmError::InvalidResponse(detail)

View file

@ -7,7 +7,7 @@ pub mod outbound;
pub mod provider;
pub mod resources;
pub use error::RouteError;
pub use error::Error;
#[derive(Clone, Default)]
pub struct CallOptions {

View file

@ -2,7 +2,7 @@ use litellm_core_utils::get_llm_provider_logic::{
CustomLlmProvider, LlmProviders, get_custom_llm_provider,
};
use crate::error::RouteError as Error;
use crate::error::Error;
#[derive(Debug)]
pub struct ResolvedProvider<'a> {

View file

@ -25,7 +25,7 @@ use litellm_host::{
protocol::Protocol,
};
use litellm_inference::{
RouteError,
Error,
caching::{Cachable, CacheRequest, StreamCachable, execute_streaming, execute_unary},
};
use rstest::{fixture, rstest};
@ -36,7 +36,7 @@ struct TestRoute;
impl Protocol for TestRoute {
type Request = Value;
type Response = Value;
type Error = RouteError;
type Error = Error;
type HostCall = Infallible;
type Chunk = Bytes;
type StreamHead = ();
@ -204,7 +204,7 @@ async fn streamed(
.chunks(3)
.map(|bytes| Ok(Bytes::copy_from_slice(bytes)))
.collect::<Vec<_>>();
let ending = fail.then_some(Err(RouteError::Unsupported("test transport failure")));
let ending = fail.then_some(Err(Error::Unsupported("test transport failure")));
Ok(CallOutput::Stream {
head: (),
chunks: stream::iter(chunks.into_iter().chain(ending)).boxed(),
@ -215,7 +215,7 @@ async fn streamed(
.unwrap()
}
async fn consume(output: OutputOf<TestRoute>) -> Result<Vec<u8>, RouteError> {
async fn consume(output: OutputOf<TestRoute>) -> Result<Vec<u8>, Error> {
let CallOutput::Stream { chunks, .. } = output else {
panic!("expected a stream");
};
@ -315,7 +315,7 @@ async fn a_provider_failure_never_populates_the_cache(cache: Arc<dyn ResponseCac
None,
|| async {
calls.fetch_add(1, Ordering::SeqCst);
Err(RouteError::Unsupported("test provider failure"))
Err(Error::Unsupported("test provider failure"))
},
)
.await;
@ -467,8 +467,8 @@ struct CacheHitAccounting {
reject: bool,
}
impl Interceptors<RouteError> for CacheHitAccounting {
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), RouteError> {
impl Interceptors<Error> for CacheHitAccounting {
async fn result_ready(&self, facts: ExecutionFacts) -> Result<(), Error> {
self.calls.fetch_add(1, Ordering::SeqCst);
let ResultSource::Cache { key } = facts.source else {
panic!("expected cache source")
@ -482,7 +482,7 @@ impl Interceptors<RouteError> for CacheHitAccounting {
);
self.key.set(key).unwrap();
if self.reject {
return Err(RouteError::Unsupported("cache accounting rejected"));
return Err(Error::Unsupported("cache accounting rejected"));
}
Ok(())
}
@ -491,11 +491,11 @@ impl Interceptors<RouteError> for CacheHitAccounting {
&self,
wire: WireRequest,
_: RequestContext,
) -> Result<WireRequest, RouteError> {
) -> Result<WireRequest, Error> {
Ok(wire)
}
async fn after_provider_response(&self, _: RawResponse) -> Result<(), RouteError> {
async fn after_provider_response(&self, _: RawResponse) -> Result<(), Error> {
Ok(())
}
}
@ -571,7 +571,7 @@ async fn cache_hits_notify_accounting_once_and_propagate_its_failure(
if reject {
assert!(matches!(
result,
Err(RouteError::Unsupported("cache accounting rejected"))
Err(Error::Unsupported("cache accounting rejected"))
));
} else {
assert_eq!(result.unwrap(), expected);
@ -590,7 +590,7 @@ async fn cache_hits_notify_accounting_once_and_propagate_its_failure(
impl Protocol for UnaryTestRoute {
type Request = Value;
type Response = Value;
type Error = RouteError;
type Error = Error;
type HostCall = Infallible;
type Chunk = Infallible;
type StreamHead = Infallible;

View file

@ -1,5 +1,5 @@
use litellm_http::transport::Error as TransportError;
use litellm_inference::RouteError;
use litellm_inference::Error;
use pyo3::{
exceptions::{PyRuntimeError, PyValueError},
prelude::*,
@ -19,9 +19,9 @@ pyo3::create_exception!(
"The provider call was already issued and failed. Args are (status, message); status is 0 when there was no HTTP response."
);
pub(crate) fn route_error_to_pyerr(error: RouteError) -> PyErr {
pub(crate) fn route_error_to_pyerr(error: Error) -> PyErr {
match error {
RouteError::Transport(TransportError::Http { status, body }) => {
Error::Transport(TransportError::Http { status, body }) => {
RustUpstreamError::new_err((status, body))
}
other => by_fault(other.is_request(), other.to_string()),
@ -42,13 +42,13 @@ mod tests {
use super::*;
#[rstest::rstest]
#[case::unsupported(RouteError::Unsupported("test capability"), true)]
#[case::invalid_provider(RouteError::InvalidProvider("unknown".into()), true)]
#[case::invalid_request(RouteError::InvalidRequest("empty messages".into()), true)]
#[case::unsupported(Error::Unsupported("test capability"), true)]
#[case::invalid_provider(Error::InvalidProvider("unknown".into()), true)]
#[case::invalid_request(Error::InvalidRequest("empty messages".into()), true)]
#[case::connection(TransportError::Connect("unreachable".into()).into(), false)]
#[case::network(TransportError::Network("timed out".into()).into(), false)]
#[case::invalid_response(RouteError::InvalidResponse("missing usage".into()), false)]
fn route_failures_are_terminal(#[case] error: RouteError, #[case] is_request: bool) {
#[case::invalid_response(Error::InvalidResponse("missing usage".into()), false)]
fn route_failures_are_terminal(#[case] error: Error, #[case] is_request: bool) {
Python::initialize();
Python::attach(|py| {
let failure = route_error_to_pyerr(error);
@ -86,14 +86,12 @@ mod tests {
fn missing_api_key_stays_a_runtime_error_while_other_auth_failures_are_value_errors() {
Python::initialize();
Python::attach(|py| {
let missing =
route_error_to_pyerr(RouteError::Auth(litellm_auth::Error::MissingApiKey {
provider: "Anthropic",
environment_variable: "ANTHROPIC_API_KEY",
}));
let missing = route_error_to_pyerr(Error::Auth(litellm_auth::Error::MissingApiKey {
provider: "Anthropic",
environment_variable: "ANTHROPIC_API_KEY",
}));
assert!(missing.is_instance_of::<PyRuntimeError>(py));
let invalid =
route_error_to_pyerr(RouteError::Auth(litellm_auth::Error::InvalidHeader));
let invalid = route_error_to_pyerr(Error::Auth(litellm_auth::Error::InvalidHeader));
assert!(invalid.is_instance_of::<PyValueError>(py));
});
}

View file

@ -7,7 +7,7 @@ use litellm_core_utils::get_llm_provider_logic::get_custom_llm_provider;
use litellm_host::{call::HostedMachine, protocol::Protocol};
use litellm_host_python::{PythonBinding, PythonHostCalls, from_py};
use litellm_http::transport::Error as TransportError;
use litellm_inference::RouteError;
use litellm_inference::Error;
use litellm_secrets::source::SecretSource;
use pyo3::{
exceptions::PyValueError,
@ -119,14 +119,14 @@ impl InferenceHost {
public_response(py, self.module, response)
}
pub fn error(&self, py: Python<'_>, error: RouteError) -> PyResult<PyErr> {
if let RouteError::Secret(source) = &error
pub fn error(&self, py: Python<'_>, error: Error) -> PyResult<PyErr> {
if let Error::Secret(source) = &error
&& let Some(original) = crate::secrets::python_error(py, source.source_error())
{
return Ok(original);
}
let native = match error {
RouteError::Transport(TransportError::Http { status, body }) => {
Error::Transport(TransportError::Http { status, body }) => {
let error = RustUpstreamError::new_err((status, body));
error
.value(py)
@ -144,7 +144,7 @@ impl InferenceHost {
}
pub(super) trait InferenceRoute: Sized + 'static {
type Protocol: Protocol<Error = RouteError>;
type Protocol: Protocol<Error = Error>;
const OPERATION: LoggingOperation;
const SYNC_CALL_TYPE: &'static str;
const ASYNC_CALL_TYPE: &'static str;