Error handling
Every fallible Rig call returns a typed error, so you can react to why something failed instead of
parsing strings. The two you’ll meet most often are PromptError (from agent.prompt(...)) and
CompletionError (from a raw completion request); embeddings return EmbeddingError and vector
stores return VectorStoreError.
The error you get from an agent
Section titled “The error you get from an agent”agent.prompt(...) returns Result<String, PromptError>. PromptError distinguishes a failed model
call from a tool failure from hitting the multi-turn limit:
match agent.prompt("What is 2 + 2?").await { Ok(reply) => println!("{reply}"), Err(PromptError::MaxTurnsError { max_turns, .. }) => { eprintln!("the model kept calling tools and hit the {max_turns}-turn limit"); } Err(PromptError::ToolError(e)) => { eprintln!("a tool returned an error: {e}"); } Err(PromptError::CompletionError(e)) => { eprintln!("the underlying model call failed: {e}"); } Err(e) => eprintln!("other prompt error: {e}"),}The error you get from a model call
Section titled “The error you get from a model call”CompletionError describes failures at the provider boundary — network, (de)serialization, or a
provider-side rejection. Matching on it lets you separate transient failures (worth retrying) from
fatal ones (worth surfacing):
match result { Ok(text) => println!("{text}"), // Transient — a retry may succeed. Err(CompletionError::HttpError(e)) => eprintln!("network/timeout, retryable: {e}"), // Fatal — the request or response was malformed. Err(CompletionError::JsonError(e)) => eprintln!("(de)serialization failed: {e}"), Err(CompletionError::ResponseError(msg)) => eprintln!("provider rejected it: {msg}"), Err(e) => eprintln!("{e}"),}Retrying transient failures
Section titled “Retrying transient failures”Rig doesn’t retry for you — that keeps the core predictable — so wrap calls in your own backoff loop. This is the idiomatic pattern: retry a bounded number of times with exponential backoff, and give up on the last attempt.
use std::time::Duration;
/// Prompt an agent, retrying a few times with exponential backoff.async fn prompt_with_retry( agent: &Agent<openai::responses_api::ResponsesCompletionModel>, input: &str, max_attempts: u32,) -> Result<String, PromptError> { let mut attempt = 0; loop { attempt += 1; match agent.prompt(input).await { Ok(reply) => return Ok(reply), Err(e) if attempt < max_attempts => { let backoff = Duration::from_millis(200 * 2u64.pow(attempt - 1)); eprintln!("attempt {attempt} failed ({e}); retrying in {backoff:?}"); tokio::time::sleep(backoff).await; } Err(e) => return Err(e), } }}attempt 1 failed (HttpError: request timed out); retrying in 200msattempt 2 failed (HttpError: request timed out); retrying in 400ms# ...succeeds on attempt 3