#[non_exhaustive]pub enum GenaiError {
Http(Error),
Parse(String),
Json(Error),
Utf8(Utf8Error),
Api {
status_code: u16,
message: String,
request_id: Option<String>,
retry_after: Option<Duration>,
},
Internal(String),
InvalidInput(String),
MalformedResponse(String),
Timeout(Duration),
ClientBuild(String),
}Expand description
Defines errors that can occur when interacting with the GenAI API.
§Example: Handling API Errors
match client.interaction().create().await {
Err(GenaiError::Api { status_code: 429, request_id, .. }) => {
tracing::warn!("Rate limited, request_id: {:?}", request_id);
// Retry with backoff
}
Err(GenaiError::Api { status_code, message, request_id }) => {
tracing::error!("API error {}: {} (request: {:?})", status_code, message, request_id);
}
// ...
}Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Http(Error)
Parse(String)
Json(Error)
Utf8(Utf8Error)
Api
API error with structured context for debugging and automated handling.
Contains the HTTP status code (for retry logic), error message, and optional request ID (for correlation with Google API logs/support).
Fields
retry_after: Option<Duration>Retry delay from Retry-After header (for 429 rate limit errors).
When present, this indicates how long to wait before retrying.
The value is parsed from the Retry-After header, which can be:
- Seconds (e.g., “120” → 120 seconds)
- HTTP date (e.g., “Wed, 21 Oct 2015 07:28:00 GMT” → duration until then)
This field is typically only populated for 429 (Too Many Requests) errors.
Internal(String)
InvalidInput(String)
MalformedResponse(String)
API returned a successful response but with unexpected or invalid content.
This indicates the API response didn’t match the expected schema,
possibly due to API evolution or an undocumented response format.
Unlike InvalidInput (user’s fault), this represents an issue with
the API response itself.
Timeout(Duration)
Request timed out after the specified duration.
This error is returned when a request exceeds the timeout configured
via with_timeout(). The duration indicates how long the request
was allowed to run before being cancelled.
ClientBuild(String)
Failed to build the HTTP client.
This typically only occurs in exceptional circumstances such as TLS backend initialization failures.
Implementations§
Source§impl GenaiError
impl GenaiError
Sourcepub fn is_retryable(&self) -> bool
pub fn is_retryable(&self) -> bool
Returns true if this error is likely transient and the request may succeed on retry.
This helper identifies errors that are typically recoverable:
- HTTP errors: Network issues, connection resets, TLS errors
- Rate limits (429): Temporary throttling, retry after backoff
- Server errors (5xx): Temporary server issues
- Timeouts: Request took too long but may succeed with retry
Errors that return false are typically permanent and retrying won’t help:
- Client errors (4xx except 429): Bad request, unauthorized, not found
- Parse/JSON errors: Response format issues
- Invalid input: Request validation failures
- Malformed response: API contract violations
§Example
use genai_rs::GenaiError;
use std::time::Duration;
fn should_retry(error: &GenaiError, attempt: u32, max_attempts: u32) -> bool {
attempt < max_attempts && error.is_retryable()
}
// Rate limit errors are retryable
let rate_limited = GenaiError::Api {
status_code: 429,
message: "Resource exhausted".to_string(),
request_id: None,
retry_after: Some(std::time::Duration::from_secs(60)),
};
assert!(rate_limited.is_retryable());
// Bad request errors are not retryable
let bad_request = GenaiError::Api {
status_code: 400,
message: "Invalid model".to_string(),
request_id: None,
retry_after: None,
};
assert!(!bad_request.is_retryable());
// Timeouts are retryable
let timeout = GenaiError::Timeout(Duration::from_secs(30));
assert!(timeout.is_retryable());§Retry Strategy
When implementing retry logic, consider:
- Use exponential backoff with jitter
- Set a maximum number of retries
- For 429 errors, use the
retry_afterfield if available (extracted fromRetry-Afterheader) - Log retries for observability
See examples/retry_with_backoff.rs for a complete retry implementation.
Sourcepub fn retry_after(&self) -> Option<Duration>
pub fn retry_after(&self) -> Option<Duration>
Returns the server-suggested retry delay for rate limit (429) errors.
This extracts the Retry-After header value that was parsed when the error
was created. Only Api errors with status code 429 typically have this field set.
§Returns
Some(Duration)if the error has aretry_aftervalueNonefor all other error types or if noRetry-Afterheader was present
§Example
use genai_rs::GenaiError;
use std::time::Duration;
async fn with_server_suggested_delay(error: &GenaiError) {
if let Some(delay) = error.retry_after() {
// Server told us how long to wait
tokio::time::sleep(delay).await;
} else {
// Fall back to our own backoff strategy
tokio::time::sleep(Duration::from_secs(1)).await;
}
}Trait Implementations§
Source§impl Debug for GenaiError
impl Debug for GenaiError
Source§impl Display for GenaiError
impl Display for GenaiError
Source§impl Error for GenaiError
impl Error for GenaiError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
Source§impl From<Error> for GenaiError
impl From<Error> for GenaiError
Source§impl From<Error> for GenaiError
impl From<Error> for GenaiError
Auto Trait Implementations§
impl Freeze for GenaiError
impl !RefUnwindSafe for GenaiError
impl Send for GenaiError
impl Sync for GenaiError
impl Unpin for GenaiError
impl !UnwindSafe for GenaiError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> ToStringFallible for Twhere
T: Display,
impl<T> ToStringFallible for Twhere
T: Display,
Source§fn try_to_string(&self) -> Result<String, TryReserveError>
fn try_to_string(&self) -> Result<String, TryReserveError>
ToString::to_string, but without panic on OOM.